From 66c06eb1ad868a7e0b56f264d447d81dd1486b5c Mon Sep 17 00:00:00 2001 From: ivanwonder Date: Sat, 15 Feb 2020 13:31:28 +0800 Subject: [PATCH] fix(language-service): provide completions for the structural directive that only injects the 'ViewContainerRef' (#35466) The completions list don't include the 'ngTemplateOutlet'. The directive is a structural directive when it has injected the 'TemplateRef' or 'ViewContainerRef'. PR Close #35466 --- packages/language-service/src/completions.ts | 6 +++--- packages/language-service/src/utils.ts | 6 ++++-- packages/language-service/test/completions_spec.ts | 1 + 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/language-service/src/completions.ts b/packages/language-service/src/completions.ts index 64abe85f5b..6c248bb727 100644 --- a/packages/language-service/src/completions.ts +++ b/packages/language-service/src/completions.ts @@ -15,7 +15,7 @@ import {getExpressionCompletions} from './expressions'; import {attributeNames, elementNames, eventNames, propertyNames} from './html_info'; import {InlineTemplate} from './template'; import * as ng from './types'; -import {diagnosticInfoFromTemplateInfo, findTemplateAstAt, getPathToNodeAtPosition, getSelectors, hasTemplateReference, inSpan, spanOf} from './utils'; +import {diagnosticInfoFromTemplateInfo, findTemplateAstAt, getPathToNodeAtPosition, getSelectors, inSpan, isStructuralDirective, spanOf} from './utils'; const HIDDEN_HTML_ELEMENTS: ReadonlySet = new Set(['html', 'script', 'noscript', 'base', 'body', 'title', 'head', 'link']); @@ -629,11 +629,11 @@ function angularAttributes(info: AstResult, elementName: string): AngularAttribu continue; } const summary = selectorMap.get(selector) !; - const isTemplateRef = hasTemplateReference(summary.type); + const hasTemplateRef = isStructuralDirective(summary.type); // attributes are listed in (attribute, value) pairs for (let i = 0; i < selector.attrs.length; i += 2) { const attr = selector.attrs[i]; - if (isTemplateRef) { + if (hasTemplateRef) { templateRefs.add(attr); } else { others.add(attr); diff --git a/packages/language-service/src/utils.ts b/packages/language-service/src/utils.ts index 4b8c062ee1..33ac9be37a 100644 --- a/packages/language-service/src/utils.ts +++ b/packages/language-service/src/utils.ts @@ -56,9 +56,11 @@ export function isNarrower(spanA: Span, spanB: Span): boolean { return spanA.start >= spanB.start && spanA.end <= spanB.end; } -export function hasTemplateReference(type: CompileTypeMetadata): boolean { +export function isStructuralDirective(type: CompileTypeMetadata): boolean { for (const diDep of type.diDeps) { - if (diDep.token && identifierName(diDep.token.identifier) === Identifiers.TemplateRef.name) { + const diDepName = identifierName(diDep.token?.identifier); + if (diDepName === Identifiers.TemplateRef.name || + diDepName === Identifiers.ViewContainerRef.name) { return true; } } diff --git a/packages/language-service/test/completions_spec.ts b/packages/language-service/test/completions_spec.ts index 2d6967570c..33cab0f1c0 100644 --- a/packages/language-service/test/completions_spec.ts +++ b/packages/language-service/test/completions_spec.ts @@ -129,6 +129,7 @@ describe('completions', () => { 'ngSwitchCase', 'ngSwitchDefault', 'ngPluralCase', + 'ngTemplateOutlet', ]); });