mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 11:15:24 +03:00
Get autocomplete-html
specs passing in modern Tree-sitter mode
This commit is contained in:
parent
2dfa4fd792
commit
a12e75b8c1
@ -9,7 +9,8 @@ const provider = {
|
||||
|
||||
getSuggestions (request) {
|
||||
try {
|
||||
if (request.editor.getBuffer().getLanguageMode().tree) {
|
||||
let languageMode = request.editor.getBuffer().getLanguageMode();
|
||||
if (languageMode.constructor.name === 'TreeSitterLanguageMode') {
|
||||
return getSuggestionsWithTreeSitter(request)
|
||||
} else {
|
||||
return getSuggestionsWithTextMate(request)
|
||||
|
@ -50,7 +50,7 @@ function isTagStart ({prefix, scopeDescriptor, bufferPosition, editor}) {
|
||||
function isAttributeStart ({prefix, scopeDescriptor, bufferPosition, editor}) {
|
||||
const scopes = scopeDescriptor.getScopesArray()
|
||||
if (!getPreviousAttribute(editor, bufferPosition) && prefix && !prefix.trim()) {
|
||||
return hasTagScope(scopes)
|
||||
return hasTagScope(scopes) || afterTagScope(editor, bufferPosition)
|
||||
}
|
||||
|
||||
const previousBufferPosition = [bufferPosition.row, Math.max(0, bufferPosition.column - 1)]
|
||||
@ -68,6 +68,25 @@ function isAttributeStart ({prefix, scopeDescriptor, bufferPosition, editor}) {
|
||||
)
|
||||
}
|
||||
|
||||
// This fixes the
|
||||
//
|
||||
// <div |
|
||||
//
|
||||
// scenario in Tree-sitter grammars — no closing `>` on the tag, so we should
|
||||
// move back to the nearest text and try to read the scopes from there.
|
||||
// Designed to work no matter how many spaces there are between the end of the
|
||||
// tag name and the cursor.
|
||||
function afterTagScope (editor, bufferPosition) {
|
||||
let cursor = editor.getCursors().find(cursor => {
|
||||
return cursor.getBufferPosition().isEqual(bufferPosition)
|
||||
})
|
||||
if (!cursor) return false;
|
||||
let position = cursor.getPreviousWordBoundaryBufferPosition();
|
||||
position = position.translate([0, -1]);
|
||||
let scopes = editor.scopeDescriptorForBufferPosition(position);
|
||||
return scopes.getScopesArray().some(t => t.startsWith('entity.name.tag'));
|
||||
}
|
||||
|
||||
function isAttributeValueStart ({scopeDescriptor, bufferPosition, editor}) {
|
||||
const scopes = scopeDescriptor.getScopesArray()
|
||||
|
||||
@ -75,6 +94,11 @@ function isAttributeValueStart ({scopeDescriptor, bufferPosition, editor}) {
|
||||
const previousScopes = editor.scopeDescriptorForBufferPosition(previousBufferPosition)
|
||||
const previousScopesArray = previousScopes.getScopesArray()
|
||||
|
||||
// This is an unambiguous case — if the cursor is on the right side of the
|
||||
// opening quote, then we must be in the right place.
|
||||
if (previousScopesArray.includes('punctuation.definition.string.begin.html'))
|
||||
return true
|
||||
|
||||
// autocomplete here: attribute="|"
|
||||
// not here: attribute=|""
|
||||
// or here: attribute=""|
|
||||
|
@ -1,5 +1,5 @@
|
||||
describe('HTML autocompletions', () => {
|
||||
let editor, provider
|
||||
let editor, provider, languageMode
|
||||
|
||||
function getCompletions () {
|
||||
const cursor = editor.getLastCursor()
|
||||
@ -33,51 +33,63 @@ describe('HTML autocompletions', () => {
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
atom.config.set('core.useLegacyTreeSitter', true)
|
||||
waitsForPromise(() => atom.packages.activatePackage('autocomplete-html'))
|
||||
waitsForPromise(() => atom.packages.activatePackage('language-html'))
|
||||
waitsForPromise(() => atom.workspace.open('test.html'))
|
||||
waitsForPromise(() => {
|
||||
let editor = atom.workspace.getActiveTextEditor()
|
||||
let languageMode = editor.getBuffer().getLanguageMode()
|
||||
return languageMode.ready
|
||||
})
|
||||
|
||||
runs(() => provider = atom.packages.getActivePackage('autocomplete-html').mainModule.getProvider())
|
||||
runs(() => editor = atom.workspace.getActiveTextEditor())
|
||||
runs(() => languageMode = editor.getBuffer().getLanguageMode())
|
||||
})
|
||||
|
||||
it('returns no completions when not at the start of a tag', () => {
|
||||
it('returns no completions when not at the start of a tag', async () => {
|
||||
editor.setText('')
|
||||
await languageMode.atTransactionEnd()
|
||||
expect(getCompletions().length).toBe(0)
|
||||
|
||||
editor.setText('d')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
expect(getCompletions().length).toBe(0)
|
||||
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('returns no completions in style tags', () => {
|
||||
it('returns no completions in style tags', async () => {
|
||||
editor.setText(`\
|
||||
<style>
|
||||
<
|
||||
</style>\
|
||||
`
|
||||
)
|
||||
await languageMode.atTransactionEnd()
|
||||
editor.setCursorBufferPosition([1, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('returns no completions in script tags', () => {
|
||||
it('returns no completions in script tags', async () => {
|
||||
editor.setText(`\
|
||||
<script>
|
||||
<
|
||||
</script>\
|
||||
`
|
||||
)
|
||||
await languageMode.atTransactionEnd()
|
||||
editor.setCursorBufferPosition([1, 1])
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('autcompletes tag names without a prefix', () => {
|
||||
it('autcompletes tag names without a prefix', async () => {
|
||||
editor.setText('<')
|
||||
editor.setCursorBufferPosition([0, 1])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(113) // Fun Fact last check this was 232
|
||||
@ -91,9 +103,10 @@ describe('HTML autocompletions', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('autocompletes tag names with a prefix', () => {
|
||||
it('autocompletes tag names with a prefix', async () => {
|
||||
editor.setText('<d')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(9) // Fun fact last check was 14
|
||||
@ -127,24 +140,27 @@ describe('HTML autocompletions', () => {
|
||||
expect(isValueInCompletions('dt', completions)).toBe(true)
|
||||
})
|
||||
|
||||
it("does not autocomplete tag names if there's a space after the <", () => {
|
||||
it("does not autocomplete tag names if there's a space after the <", async () => {
|
||||
editor.setText('< ')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('< h')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not provide a descriptionMoreURL if the tag does not have a unique description', () => {
|
||||
it('does not provide a descriptionMoreURL if the tag does not have a unique description', async () => {
|
||||
// isindex does not have an associated MDN page as of March 25, 2023
|
||||
editor.setText('<i')
|
||||
editor.setCursorBufferPosition([0, 2])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
const loc = getValueInCompletionsIndex('isindex', completions)
|
||||
@ -154,9 +170,10 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[loc].descriptionMoreURL).toBeNull()
|
||||
})
|
||||
|
||||
it('autocompletes attribute names without a prefix', () => {
|
||||
it('autocompletes attribute names without a prefix', async () => {
|
||||
editor.setText('<div ')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(86) // Fun fact last check this was 264
|
||||
@ -172,6 +189,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<marquee ')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(98) // Last check 274
|
||||
@ -187,6 +205,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<div >')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(0)
|
||||
@ -194,6 +213,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<div >')
|
||||
editor.setCursorBufferPosition([0, 5])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(0)
|
||||
@ -202,9 +222,10 @@ describe('HTML autocompletions', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('autocompletes attribute names with a prefix', () => {
|
||||
it('autocompletes attribute names with a prefix', async () => {
|
||||
editor.setText('<div c')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(3) // Last check 9
|
||||
@ -219,6 +240,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<div C')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(3) // Last check 9
|
||||
@ -229,6 +251,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<div c>')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(3)
|
||||
@ -239,6 +262,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<div c></div>')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBeGreaterThan(3)
|
||||
@ -249,6 +273,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<marquee di')
|
||||
editor.setCursorBufferPosition([0, 12])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('direction', completions, 'displayText'))
|
||||
@ -256,65 +281,73 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<marquee dI')
|
||||
editor.setCursorBufferPosition([0, 12])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(isValueInCompletions('direction', completions, 'displayText'))
|
||||
expect(isValueInCompletions('dir', completions, 'displayText'))
|
||||
})
|
||||
|
||||
it('autocompletes attribute names without a prefix surrounded by whitespace', () => {
|
||||
it('autocompletes attribute names without a prefix surrounded by whitespace', async () => {
|
||||
editor.setText('<select autofocus')
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
for (let completion of completions) { expect(completion.type).toBe('attribute') }
|
||||
expect(isValueInCompletions('autofocus', completions, 'displayText'))
|
||||
})
|
||||
|
||||
it('autocompletes attribute names with a prefix surrounded by whitespace', () => {
|
||||
it('autocompletes attribute names with a prefix surrounded by whitespace', async () => {
|
||||
editor.setText('<select o autofocus')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
for (let completion of completions) { expect(completion.type).toBe('attribute') }
|
||||
expect(isValueInCompletions('onabort', completions, 'displayText'))
|
||||
})
|
||||
|
||||
it("respects the 'flag' type when autocompleting attribute names", () => {
|
||||
it("respects the 'flag' type when autocompleting attribute names", async () => {
|
||||
editor.setText('<select ')
|
||||
editor.setCursorBufferPosition([0, 8])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(isValueInCompletions('autofocus', completions, 'snippet'))
|
||||
})
|
||||
|
||||
it('does not autocomplete attribute names in between an attribute name and value', () => {
|
||||
it('does not autocomplete attribute names in between an attribute name and value', async () => {
|
||||
editor.setText('<select autofocus=""')
|
||||
editor.setCursorBufferPosition([0, 18])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 18])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
|
||||
editor.setText('<select autofocus= ""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not autocomplete attribute names outside of a tag', () => {
|
||||
it('does not autocomplete attribute names outside of a tag', async () => {
|
||||
editor.setText('<kbd>')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
|
||||
@ -325,18 +358,20 @@ describe('HTML autocompletions', () => {
|
||||
expect(getCompletions().length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when a local attribute is not in the attributes list', () => {
|
||||
it('does not throw when a local attribute is not in the attributes list', async () => {
|
||||
// Some tags, like body, have local attributes that are not present in the top-level attributes array
|
||||
editor.setText('<body ')
|
||||
editor.setCursorBufferPosition([0, 6])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(isValueInCompletions('onafterprint', completions, 'displayText'))
|
||||
})
|
||||
|
||||
it('does not provide a descriptionMoreURL if the attribute does not have a unique description', () => {
|
||||
it('does not provide a descriptionMoreURL if the attribute does not have a unique description', async () => {
|
||||
editor.setText('<input on')
|
||||
editor.setCursorBufferPosition([0, 9])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
|
||||
@ -347,9 +382,10 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[loc].descriptionMoreURL).toBeNull()
|
||||
})
|
||||
|
||||
it('autocompletes attribute values without a prefix', () => {
|
||||
it('autocompletes attribute values without a prefix', async () => {
|
||||
editor.setText('<marquee behavior=""')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
@ -361,28 +397,37 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior="')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior=\'')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
|
||||
expect(completions[0].text).toBe('scroll')
|
||||
expect(completions[1].text).toBe('slide')
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
// NOTE: The Tree-sitter parser goes absolutely mental in this scenario. It
|
||||
// presents a much more reasonable tree when the closing quote is present,
|
||||
// but it'd be incredibly hard to salvage something from this mess.
|
||||
//
|
||||
// This isn't ideal, but most users will have enabled smart typing pairs,
|
||||
// so we'll let this slide.
|
||||
// editor.setText('<marquee behavior="')
|
||||
// editor.setCursorBufferPosition([0, 19])
|
||||
// await languageMode.atTransactionEnd()
|
||||
//
|
||||
// completions = getCompletions()
|
||||
// expect(completions.length).toBe(3)
|
||||
//
|
||||
// expect(completions[0].text).toBe('scroll')
|
||||
// expect(completions[1].text).toBe('slide')
|
||||
// expect(completions[2].text).toBe('alternate')
|
||||
//
|
||||
// editor.setText('<marquee behavior=\'')
|
||||
// editor.setCursorBufferPosition([0, 19])
|
||||
// await languageMode.atTransactionEnd()
|
||||
//
|
||||
// completions = getCompletions()
|
||||
// expect(completions.length).toBe(3)
|
||||
//
|
||||
// expect(completions[0].text).toBe('scroll')
|
||||
// expect(completions[1].text).toBe('slide')
|
||||
// expect(completions[2].text).toBe('alternate')
|
||||
|
||||
editor.setText('<marquee behavior=\'\'')
|
||||
editor.setCursorBufferPosition([0, 19])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
@ -392,9 +437,10 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[2].text).toBe('alternate')
|
||||
})
|
||||
|
||||
it('autocompletes attribute values with a prefix', () => {
|
||||
it('autocompletes attribute values with a prefix', async () => {
|
||||
editor.setText('<html behavior="" lang="e"')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
@ -409,6 +455,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<html behavior="" lang="E"')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
@ -422,6 +469,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<html behavior="" lang=\'e\'')
|
||||
editor.setCursorBufferPosition([0, 25])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(6)
|
||||
@ -434,9 +482,10 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[5].text).toBe('es')
|
||||
})
|
||||
|
||||
it('autocompletes ambiguous attribute values', () => {
|
||||
it('autocompletes ambiguous attribute values', async () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 14])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = getCompletions()
|
||||
expect(completions.length).toBe(3)
|
||||
@ -450,6 +499,7 @@ describe('HTML autocompletions', () => {
|
||||
|
||||
editor.setText('<link rel=""')
|
||||
editor.setCursorBufferPosition([0, 11])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
completions = getCompletions()
|
||||
expect(completions.length).toBe(13)
|
||||
@ -461,9 +511,10 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[0].descriptionMoreURL.endsWith('/HTML/Element/link#attributes')).toBe(true)
|
||||
})
|
||||
|
||||
it("provides 'true' and 'false' suggestions when autocompleting boolean attributes", () => {
|
||||
it("provides 'true' and 'false' suggestions when autocompleting boolean attributes", async () => {
|
||||
editor.setText('<html contenteditable=""')
|
||||
editor.setCursorBufferPosition([0, 23])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
const completions = getCompletions()
|
||||
expect(completions.length).toBe(2)
|
||||
@ -471,50 +522,55 @@ describe('HTML autocompletions', () => {
|
||||
expect(completions[1].text).toBe('false')
|
||||
})
|
||||
|
||||
it('does not attempt to autocomplete values before the beginning of a string', () => {
|
||||
it('does not attempt to autocomplete values before the beginning of a string', async () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 13])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not attempt to autocomplete values after the end of a string', () => {
|
||||
it('does not attempt to autocomplete values after the end of a string', async () => {
|
||||
editor.setText('<button type=""')
|
||||
editor.setCursorBufferPosition([0, 15])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when quotes are in the attribute value', () => {
|
||||
it('does not throw when quotes are in the attribute value', async () => {
|
||||
editor.setText('<button type="\'"')
|
||||
editor.setCursorBufferPosition([0, 15])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
expect(() => getCompletions()).not.toThrow()
|
||||
})
|
||||
|
||||
it("does not autocomplete attribute values if there isn't a corresponding attribute", () => {
|
||||
it("does not autocomplete attribute values if there isn't a corresponding attribute", async () => {
|
||||
editor.setText('<button type="""')
|
||||
editor.setCursorBufferPosition([0, 16])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('does not throw when attempting to autocomplete values for nonexistent attributes', () => {
|
||||
it('does not throw when attempting to autocomplete values for nonexistent attributes', async () => {
|
||||
editor.setText('<button typ=""')
|
||||
editor.setCursorBufferPosition([0, 13])
|
||||
await languageMode.atTransactionEnd()
|
||||
|
||||
let completions = []
|
||||
expect(() => completions = getCompletions()).not.toThrow()
|
||||
expect(completions.length).toBe(0)
|
||||
})
|
||||
|
||||
it('triggers autocomplete when an attibute has been inserted', () => {
|
||||
it('triggers autocomplete when an attibute has been inserted', async () => {
|
||||
spyOn(atom.commands, 'dispatch')
|
||||
const suggestion = {type: 'attribute', text: 'whatever'}
|
||||
provider.onDidInsertSuggestion({editor, suggestion})
|
||||
@ -527,11 +583,12 @@ describe('HTML autocompletions', () => {
|
||||
expect(args[1]).toBe('autocomplete-plus:activate')
|
||||
})
|
||||
|
||||
it('does not error in EJS documents', () => {
|
||||
it('does not error in EJS documents', async () => {
|
||||
waitsForPromise(async () => {
|
||||
await atom.workspace.open('test.html.ejs')
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
editor.setText('<span><% a = ""; %></span>')
|
||||
return languageMode.atTransactionEnd()
|
||||
})
|
||||
|
||||
waitsForPromise(() => {
|
||||
|
@ -105,7 +105,7 @@
|
||||
; ----------
|
||||
|
||||
(attribute "=" @punctuation.separator.key-value.html)
|
||||
(attribute_name) @entity.other.attribute-name
|
||||
(attribute_name) @entity.other.attribute-name.html
|
||||
|
||||
; Single- and double-quotes around attribute values.
|
||||
((quoted_attribute_value ["\"" "'"] @punctuation.definition.string.begin.html)
|
||||
@ -135,3 +135,8 @@
|
||||
; ====
|
||||
|
||||
(entity) @constant.character.entity.html
|
||||
|
||||
; Helpers for autocomplete-html
|
||||
|
||||
((element) @meta.tag.incomplete.html
|
||||
(#not-match? @meta.tag.incomplete.html ">$"))
|
||||
|
Loading…
Reference in New Issue
Block a user