fix(language-service): fix autocomplete info display for some cases (#42472)

Before this commit, attribute completion display parts were retrieved
but not assigned. In addition, the switch case was non-exhaustive
because it did not include `StructuralDirectiveAttribute`.

PR Close #42472
This commit is contained in:
Andrew Scott 2021-06-03 15:15:16 -07:00 committed by Jessica Janiuk
parent f85a120b7b
commit a493ea9bcb
3 changed files with 20 additions and 6 deletions

View File

@ -579,6 +579,7 @@ export class CompletionBuilder<N extends TmplAstNode|AST> {
displayParts = info.displayParts; displayParts = info.displayParts;
documentation = info.documentation; documentation = info.documentation;
break; break;
case AttributeCompletionKind.StructuralDirectiveAttribute:
case AttributeCompletionKind.DirectiveInput: case AttributeCompletionKind.DirectiveInput:
case AttributeCompletionKind.DirectiveOutput: case AttributeCompletionKind.DirectiveOutput:
const propertySymbol = getAttributeCompletionSymbol(completion, this.typeChecker); const propertySymbol = getAttributeCompletionSymbol(completion, this.typeChecker);
@ -586,11 +587,17 @@ export class CompletionBuilder<N extends TmplAstNode|AST> {
return undefined; return undefined;
} }
let kind: DisplayInfoKind;
if (completion.kind === AttributeCompletionKind.DirectiveInput) {
kind = DisplayInfoKind.PROPERTY;
} else if (completion.kind === AttributeCompletionKind.DirectiveOutput) {
kind = DisplayInfoKind.EVENT;
} else {
kind = DisplayInfoKind.DIRECTIVE;
}
info = getTsSymbolDisplayInfo( info = getTsSymbolDisplayInfo(
this.tsLS, this.typeChecker, propertySymbol, this.tsLS, this.typeChecker, propertySymbol, kind, completion.directive.tsSymbol.name);
completion.kind === AttributeCompletionKind.DirectiveInput ? DisplayInfoKind.PROPERTY :
DisplayInfoKind.EVENT,
completion.directive.tsSymbol.name);
if (info === null) { if (info === null) {
return undefined; return undefined;
} }
@ -602,7 +609,7 @@ export class CompletionBuilder<N extends TmplAstNode|AST> {
name: entryName, name: entryName,
kind: unsafeCastDisplayInfoKindToScriptElementKind(kind), kind: unsafeCastDisplayInfoKindToScriptElementKind(kind),
kindModifiers: ts.ScriptElementKindModifier.none, kindModifiers: ts.ScriptElementKindModifier.none,
displayParts: [], displayParts,
documentation, documentation,
}; };
} }

View File

@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {isNamedClassDeclaration} from '@angular/compiler-cli/src/ngtsc/reflection';
import {DirectiveInScope, ReferenceSymbol, ShimLocation, Symbol, SymbolKind, VariableSymbol} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; import {DirectiveInScope, ReferenceSymbol, ShimLocation, Symbol, SymbolKind, VariableSymbol} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
import * as ts from 'typescript'; import * as ts from 'typescript';
@ -155,7 +156,9 @@ export function getTsSymbolDisplayInfo(
tsLS: ts.LanguageService, checker: ts.TypeChecker, symbol: ts.Symbol, kind: DisplayInfoKind, tsLS: ts.LanguageService, checker: ts.TypeChecker, symbol: ts.Symbol, kind: DisplayInfoKind,
ownerName: string|null): DisplayInfo|null { ownerName: string|null): DisplayInfo|null {
const decl = symbol.valueDeclaration; const decl = symbol.valueDeclaration;
if (decl === undefined || (!ts.isPropertyDeclaration(decl) && !ts.isMethodDeclaration(decl)) || if (decl === undefined ||
(!ts.isPropertyDeclaration(decl) && !ts.isMethodDeclaration(decl) &&
!isNamedClassDeclaration(decl)) ||
!ts.isIdentifier(decl.name)) { !ts.isIdentifier(decl.name)) {
return null; return null;
} }

View File

@ -586,6 +586,10 @@ describe('completions', () => {
unsafeCastDisplayInfoKindToScriptElementKind(DisplayInfoKind.DIRECTIVE), unsafeCastDisplayInfoKindToScriptElementKind(DisplayInfoKind.DIRECTIVE),
['ngFor']); ['ngFor']);
expectReplacementText(completions, templateFile.contents, 'ng'); expectReplacementText(completions, templateFile.contents, 'ng');
const details = templateFile.getCompletionEntryDetails(
'ngFor', /* formatOptions */ undefined,
/* preferences */ undefined)!;
expect(toText(details.displayParts)).toEqual('(directive) NgFor.NgFor: NgFor');
}); });
it('should return structural directive completions for just the structural marker', () => { it('should return structural directive completions for just the structural marker', () => {