diff --git a/src/builtin-addons/core/template-completion-provider.ts b/src/builtin-addons/core/template-completion-provider.ts index 7bb84ec0..9231078a 100644 --- a/src/builtin-addons/core/template-completion-provider.ts +++ b/src/builtin-addons/core/template-completion-provider.ts @@ -576,14 +576,15 @@ export default class TemplateCompletionProvider { const yields = await this.getParentComponentYields(focusPath.parent); completions.push(...yields); - } else if (isAngleComponentPath(focusPath) && !isNamedBlockName(focusPath)) { + } else if (isAngleComponentPath(focusPath)) { logDebugInfo('isAngleComponentPath'); // const candidates = await this.getAllAngleBracketComponents(root); const scopedValues = this.getExtendedScopedValues(focusPath); + const yields = await this.getParentComponentYields(focusPath.parent); logDebugInfo(candidates, scopedValues); - completions.push(...uniqBy([...candidates, ...scopedValues], 'label')); + completions.push(...uniqBy([...yields, ...candidates, ...scopedValues], 'label')); } else if (isScopedAngleTagName(focusPath)) { // {{#let foo as |bar|}} ", + "kind": 6, + "label": ":main", + "textEdit": Object { + "newText": ":main", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/hello.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "Hello", + "textEdit": Object { + "newText": "Hello", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/darling.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "Darling", + "textEdit": Object { + "newText": "Darling", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/world.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "World", + "textEdit": Object { + "newText": "World", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, +] +`; + +exports[`integration async fs enabled: false autocomplete works for angle component yielded blocks 1`] = ` Array [ Object { "detail": "Named block (Slot) for ", @@ -3776,7 +3867,7 @@ Array [ ] `; -exports[`integration async fs enabled: false autocomplete works for multiple angle component slots 1`] = ` +exports[`integration async fs enabled: false autocomplete works for multiple angle component yielded blocks 1`] = ` Array [ Object { "detail": "Named block (Slot) for ", @@ -7306,18 +7397,17 @@ Object { "resolveProvider": true, "triggerCharacters": Array [ ".", - "::", + ":", "$", "=", "/", - "{{", + "{", "(", "<", "@", - "this.", - "<:", "\\"", "'", + "#", ], }, "definitionProvider": true, @@ -7588,7 +7678,99 @@ Array [ ] `; -exports[`integration async fs enabled: true autocomplete works for angle component slots 1`] = ` +exports[`integration async fs enabled: true autocomplete includes yielded blocks in angle component completions 1`] = ` +Array [ + Object { + "detail": "Named block (Slot) for ", + "kind": 6, + "label": ":main", + "textEdit": Object { + "newText": ":main", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/hello.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "Hello", + "textEdit": Object { + "newText": "Hello", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/darling.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "Darling", + "textEdit": Object { + "newText": "Darling", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, + Object { + "data": Object { + "files": Array [ + "app/components/world.hbs", + ], + }, + "detail": "component", + "kind": 7, + "label": "World", + "textEdit": Object { + "newText": "World", + "range": Object { + "end": Object { + "character": 10, + "line": 0, + }, + "start": Object { + "character": 10, + "line": 0, + }, + }, + }, + }, +] +`; + +exports[`integration async fs enabled: true autocomplete works for angle component yielded blocks 1`] = ` Array [ Object { "detail": "Named block (Slot) for ", @@ -7611,7 +7793,7 @@ Array [ ] `; -exports[`integration async fs enabled: true autocomplete works for multiple angle component slots 1`] = ` +exports[`integration async fs enabled: true autocomplete works for multiple angle component yielded blocks 1`] = ` Array [ Object { "detail": "Named block (Slot) for ", diff --git a/test/integration-test.ts b/test/integration-test.ts index 7296a9e4..321778d6 100644 --- a/test/integration-test.ts +++ b/test/integration-test.ts @@ -1811,7 +1811,7 @@ describe('integration', function () { }); }); - it('autocomplete works for angle component slots', async () => { + it('autocomplete works for angle component yielded blocks', async () => { const result = await getResult( CompletionRequest.method, connection, @@ -1830,7 +1830,7 @@ describe('integration', function () { expect(result.response).toMatchSnapshot(); }); - it('autocomplete works for multiple angle component slots', async () => { + it('autocomplete works for multiple angle component yielded blocks', async () => { const result = await getResult( CompletionRequest.method, connection, @@ -1849,6 +1849,26 @@ describe('integration', function () { expect(result.response).toMatchSnapshot(); }); + it('autocomplete includes yielded blocks in angle component completions', async () => { + const result = await getResult( + CompletionRequest.method, + connection, + { + app: { + components: { + 'hello.hbs': '<', + 'world.hbs': 'Hello World', + 'darling.hbs': '{{yield to="main"}}', + }, + }, + }, + 'app/components/hello.hbs', + { line: 0, character: 10 } + ); + + expect(result.response).toMatchSnapshot(); + }); + describe('Project class resolution, based on fs path and file structure', () => { it('able to resolve main project if top-level addon is registered', async () => { const files = {