From 6e4e68cb3012b848d2a90bd2722ffa1ea0e735d8 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 10 Dec 2020 11:13:11 -0800 Subject: [PATCH] refactor(compiler-cli): Add flag to TCB for non-diagnostic requests (#40071) The TCB utility functions used to find nodes in the TCB are currently configured to ignore results when an ignore marker is found. However, these ignore markers are only meant to affect diagnostics requests. The Language Service may have a need to find nodes with diagnostic ignore markers. The most common example of this would be finding references for generic directives. The reference appears to the generic directive's class appears on the type ctor in the TCB, which is ignored for diagnostic purposes. These functions should only skip results when the request is in the context of a larger request for _diagnostics_. In all other cases, we should get matches, even if a diagnostic ignore marker is encountered. PR Close #40071 --- .../src/ngtsc/typecheck/src/checker.ts | 7 ++--- .../src/ngtsc/typecheck/src/diagnostics.ts | 3 ++- .../src/ngtsc/typecheck/src/tcb_util.ts | 26 +++++++++++-------- .../ivy/test/references_spec.ts | 17 ++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts index 0badb22070..0a032a995c 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts @@ -121,12 +121,12 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker { throw new Error(`Error: no shim file in program: ${shimPath}`); } - let tcb: ts.Node|null = findTypeCheckBlock(shimSf, id); + let tcb: ts.Node|null = findTypeCheckBlock(shimSf, id, /*isDiagnosticsRequest*/ false); if (tcb === null) { // Try for an inline block. const inlineSf = getSourceFileOrError(program, sfPath); - tcb = findTypeCheckBlock(inlineSf, id); + tcb = findTypeCheckBlock(inlineSf, id, /*isDiagnosticsRequest*/ false); } let data: TemplateData|null = null; @@ -194,7 +194,8 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker { if (shimSf === undefined) { return null; } - return getTemplateMapping(shimSf, positionInShimFile, fileRecord.sourceManager); + return getTemplateMapping( + shimSf, positionInShimFile, fileRecord.sourceManager, /*isDiagnosticsRequest*/ false); } generateAllTypeCheckBlocks() { diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/diagnostics.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/diagnostics.ts index 02a22ef292..cd828872b6 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/diagnostics.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/diagnostics.ts @@ -91,7 +91,8 @@ export function translateDiagnostic( if (diagnostic.file === undefined || diagnostic.start === undefined) { return null; } - const fullMapping = getTemplateMapping(diagnostic.file, diagnostic.start, resolver); + const fullMapping = getTemplateMapping( + diagnostic.file, diagnostic.start, resolver, /*isDiagnosticsRequest*/ true); if (fullMapping === null) { return null; } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/tcb_util.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/tcb_util.ts index 7bdc189dcb..ac4f3cfb5e 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/tcb_util.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/tcb_util.ts @@ -54,10 +54,10 @@ export function requiresInlineTypeCheckBlock(node: ClassDeclaration { assertTextSpans(refs, ['
', 'Dir', 'Dir2']); assertFileNames(refs, ['app.ts', 'dir.ts', 'dir2.ts']); }); + + it('should be able to request references for generic directives', () => { + const {text, cursor} = extractCursorInfo(` + import {Component, NgModule} from '@angular/core'; + + @Component({template: '
'}) + export class AppCmp { + items = []; + } + `); + const appFile = {name: _('/app.ts'), contents: text}; + env = createModuleWithDeclarations([appFile]); + const refs = getReferencesAtPosition(_('/app.ts'), cursor)!; + expect(refs.length).toBe(6); + assertTextSpans(refs, ['
', 'NgForOf']); + assertFileNames(refs, ['index.d.ts', 'app.ts']); + }); }); describe('components', () => {