fix(language-service): Insert parentheses for method completion (#33860)

This commit leverages the `insertText` field in `ts.CompletionEntry` to
return a completion text for class methods that includes parentheses.

PR closes https://github.com/angular/vscode-ng-language-service/issues/15

PR Close #33860
This commit is contained in:
Keen Yee Liau 2019-11-15 12:06:00 -08:00 committed by Miško Hevery
parent c60d7563a8
commit dd944ef73f
4 changed files with 102 additions and 44 deletions

View File

@ -12,222 +12,266 @@
{ {
"name": "anchor", "name": "anchor",
"kind": "method", "kind": "method",
"sortText": "anchor" "sortText": "anchor",
"insertText": "anchor()"
}, },
{ {
"name": "big", "name": "big",
"kind": "method", "kind": "method",
"sortText": "big" "sortText": "big",
"insertText": "big()"
}, },
{ {
"name": "blink", "name": "blink",
"kind": "method", "kind": "method",
"sortText": "blink" "sortText": "blink",
"insertText": "blink()"
}, },
{ {
"name": "bold", "name": "bold",
"kind": "method", "kind": "method",
"sortText": "bold" "sortText": "bold",
"insertText": "bold()"
}, },
{ {
"name": "charAt", "name": "charAt",
"kind": "method", "kind": "method",
"sortText": "charAt" "sortText": "charAt",
"insertText": "charAt()"
}, },
{ {
"name": "charCodeAt", "name": "charCodeAt",
"kind": "method", "kind": "method",
"sortText": "charCodeAt" "sortText": "charCodeAt",
"insertText": "charCodeAt()"
}, },
{ {
"name": "codePointAt", "name": "codePointAt",
"kind": "method", "kind": "method",
"sortText": "codePointAt" "sortText": "codePointAt",
"insertText": "codePointAt()"
}, },
{ {
"name": "concat", "name": "concat",
"kind": "method", "kind": "method",
"sortText": "concat" "sortText": "concat",
"insertText": "concat()"
}, },
{ {
"name": "endsWith", "name": "endsWith",
"kind": "method", "kind": "method",
"sortText": "endsWith" "sortText": "endsWith",
"insertText": "endsWith()"
}, },
{ {
"name": "fixed", "name": "fixed",
"kind": "method", "kind": "method",
"sortText": "fixed" "sortText": "fixed",
"insertText": "fixed()"
}, },
{ {
"name": "fontcolor", "name": "fontcolor",
"kind": "method", "kind": "method",
"sortText": "fontcolor" "sortText": "fontcolor",
"insertText": "fontcolor()"
}, },
{ {
"name": "fontsize", "name": "fontsize",
"kind": "method", "kind": "method",
"sortText": "fontsize" "sortText": "fontsize",
"insertText": "fontsize()"
}, },
{ {
"name": "includes", "name": "includes",
"kind": "method", "kind": "method",
"sortText": "includes" "sortText": "includes",
"insertText": "includes()"
}, },
{ {
"name": "indexOf", "name": "indexOf",
"kind": "method", "kind": "method",
"sortText": "indexOf" "sortText": "indexOf",
"insertText": "indexOf()"
}, },
{ {
"name": "italics", "name": "italics",
"kind": "method", "kind": "method",
"sortText": "italics" "sortText": "italics",
"insertText": "italics()"
}, },
{ {
"name": "lastIndexOf", "name": "lastIndexOf",
"kind": "method", "kind": "method",
"sortText": "lastIndexOf" "sortText": "lastIndexOf",
"insertText": "lastIndexOf()"
}, },
{ {
"name": "length", "name": "length",
"kind": "property", "kind": "property",
"sortText": "length" "sortText": "length",
"insertText": "length"
}, },
{ {
"name": "link", "name": "link",
"kind": "method", "kind": "method",
"sortText": "link" "sortText": "link",
"insertText": "link()"
}, },
{ {
"name": "localeCompare", "name": "localeCompare",
"kind": "method", "kind": "method",
"sortText": "localeCompare" "sortText": "localeCompare",
"insertText": "localeCompare()"
}, },
{ {
"name": "match", "name": "match",
"kind": "method", "kind": "method",
"sortText": "match" "sortText": "match",
"insertText": "match()"
}, },
{ {
"name": "normalize", "name": "normalize",
"kind": "method", "kind": "method",
"sortText": "normalize" "sortText": "normalize",
"insertText": "normalize()"
}, },
{ {
"name": "padEnd", "name": "padEnd",
"kind": "method", "kind": "method",
"sortText": "padEnd" "sortText": "padEnd",
"insertText": "padEnd()"
}, },
{ {
"name": "padStart", "name": "padStart",
"kind": "method", "kind": "method",
"sortText": "padStart" "sortText": "padStart",
"insertText": "padStart()"
}, },
{ {
"name": "repeat", "name": "repeat",
"kind": "method", "kind": "method",
"sortText": "repeat" "sortText": "repeat",
"insertText": "repeat()"
}, },
{ {
"name": "replace", "name": "replace",
"kind": "method", "kind": "method",
"sortText": "replace" "sortText": "replace",
"insertText": "replace()"
}, },
{ {
"name": "search", "name": "search",
"kind": "method", "kind": "method",
"sortText": "search" "sortText": "search",
"insertText": "search()"
}, },
{ {
"name": "slice", "name": "slice",
"kind": "method", "kind": "method",
"sortText": "slice" "sortText": "slice",
"insertText": "slice()"
}, },
{ {
"name": "small", "name": "small",
"kind": "method", "kind": "method",
"sortText": "small" "sortText": "small",
"insertText": "small()"
}, },
{ {
"name": "split", "name": "split",
"kind": "method", "kind": "method",
"sortText": "split" "sortText": "split",
"insertText": "split()"
}, },
{ {
"name": "startsWith", "name": "startsWith",
"kind": "method", "kind": "method",
"sortText": "startsWith" "sortText": "startsWith",
"insertText": "startsWith()"
}, },
{ {
"name": "strike", "name": "strike",
"kind": "method", "kind": "method",
"sortText": "strike" "sortText": "strike",
"insertText": "strike()"
}, },
{ {
"name": "sub", "name": "sub",
"kind": "method", "kind": "method",
"sortText": "sub" "sortText": "sub",
"insertText": "sub()"
}, },
{ {
"name": "substr", "name": "substr",
"kind": "method", "kind": "method",
"sortText": "substr" "sortText": "substr",
"insertText": "substr()"
}, },
{ {
"name": "substring", "name": "substring",
"kind": "method", "kind": "method",
"sortText": "substring" "sortText": "substring",
"insertText": "substring()"
}, },
{ {
"name": "sup", "name": "sup",
"kind": "method", "kind": "method",
"sortText": "sup" "sortText": "sup",
"insertText": "sup()"
}, },
{ {
"name": "toLocaleLowerCase", "name": "toLocaleLowerCase",
"kind": "method", "kind": "method",
"sortText": "toLocaleLowerCase" "sortText": "toLocaleLowerCase",
"insertText": "toLocaleLowerCase()"
}, },
{ {
"name": "toLocaleUpperCase", "name": "toLocaleUpperCase",
"kind": "method", "kind": "method",
"sortText": "toLocaleUpperCase" "sortText": "toLocaleUpperCase",
"insertText": "toLocaleUpperCase()"
}, },
{ {
"name": "toLowerCase", "name": "toLowerCase",
"kind": "method", "kind": "method",
"sortText": "toLowerCase" "sortText": "toLowerCase",
"insertText": "toLowerCase()"
}, },
{ {
"name": "toString", "name": "toString",
"kind": "method", "kind": "method",
"sortText": "toString" "sortText": "toString",
"insertText": "toString()"
}, },
{ {
"name": "toUpperCase", "name": "toUpperCase",
"kind": "method", "kind": "method",
"sortText": "toUpperCase" "sortText": "toUpperCase",
"insertText": "toUpperCase()"
}, },
{ {
"name": "trim", "name": "trim",
"kind": "method", "kind": "method",
"sortText": "trim" "sortText": "trim",
"insertText": "trim()"
}, },
{ {
"name": "trimLeft", "name": "trimLeft",
"kind": "method", "kind": "method",
"sortText": "trimLeft" "sortText": "trimLeft",
"insertText": "trimLeft()"
}, },
{ {
"name": "trimRight", "name": "trimRight",
"kind": "method", "kind": "method",
"sortText": "trimRight" "sortText": "trimRight",
"insertText": "trimRight()"
}, },
{ {
"name": "valueOf", "name": "valueOf",
"kind": "method", "kind": "method",
"sortText": "valueOf" "sortText": "valueOf",
"insertText": "valueOf()"
} }
] ]
} }

View File

@ -442,6 +442,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
name: s.name, name: s.name,
kind: s.kind as ng.CompletionKind, kind: s.kind as ng.CompletionKind,
sortText: s.name, sortText: s.name,
insertText: s.callable ? `${s.name}()` : s.name,
}); });
} }
} }

View File

@ -213,6 +213,18 @@ describe('completions', () => {
expectContain(completions, CompletionKind.METHOD, ['myClick']); expectContain(completions, CompletionKind.METHOD, ['myClick']);
}); });
it('for methods should include parentheses', () => {
mockHost.override(TEST_TEMPLATE, `<div (click)="~{cursor}"></div>`);
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'cursor');
const completions = ngLS.getCompletionsAt(TEST_TEMPLATE, marker.start);
expect(completions).toBeDefined();
expect(completions !.entries).toContain(jasmine.objectContaining({
name: 'myClick',
kind: CompletionKind.METHOD as any,
insertText: 'myClick()',
}));
});
describe('in external template', () => { describe('in external template', () => {
it('should be able to get entity completions in external template', () => { it('should be able to get entity completions in external template', () => {
const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'entity-amp'); const marker = mockHost.getLocationMarkerFor(TEST_TEMPLATE, 'entity-amp');

View File

@ -128,6 +128,7 @@ describe('plugin', () => {
kind: CompletionKind.PROPERTY as any, kind: CompletionKind.PROPERTY as any,
sortText: 'children', sortText: 'children',
replacementSpan: {start: 182, length: 8}, replacementSpan: {start: 182, length: 8},
insertText: 'children',
}, },
]); ]);
}); });