feat(language-service): add command for getting components for a template file (#40655)

This commit adds a feature to the Angular Language Service that enables
getting the locations for components that use a template file.

Part of https://github.com/angular/vscode-ng-language-service/issues/1081

PR Close #40655
This commit is contained in:
Andrew Scott 2021-01-28 10:31:04 -08:00 committed by Alex Rickabaugh
parent 00070376ed
commit 5cde4ad591
4 changed files with 47 additions and 2 deletions

View File

@ -33,10 +33,13 @@ export type GetTcbResponse = {
selections: ts.TextSpan[],
}|undefined;
export type GetComponentLocationsForTemplateResponse = ts.DocumentSpan[];
/**
* `NgLanguageService` describes an instance of an Angular language service,
* whose API surface is a strict superset of TypeScript's language service.
*/
export interface NgLanguageService extends ts.LanguageService {
getTcb(fileName: string, position: number): GetTcbResponse;
getComponentLocationsForTemplate(fileName: string): GetComponentLocationsForTemplateResponse;
}

View File

@ -11,11 +11,13 @@ import {CompilerOptions, ConfigurationHost, readConfiguration} from '@angular/co
import {NgCompiler} from '@angular/compiler-cli/src/ngtsc/core';
import {ErrorCode, ngErrorCode} from '@angular/compiler-cli/src/ngtsc/diagnostics';
import {absoluteFrom, absoluteFromSourceFile, AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/file_system';
import {isNamedClassDeclaration} from '@angular/compiler-cli/src/ngtsc/reflection';
import {TypeCheckShimGenerator} from '@angular/compiler-cli/src/ngtsc/typecheck';
import {OptimizeFor, TypeCheckingProgramStrategy} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
import {findFirstMatchingNode} from '@angular/compiler-cli/src/ngtsc/typecheck/src/comments';
import * as ts from 'typescript/lib/tsserverlibrary';
import {GetTcbResponse} from '../api';
import {GetComponentLocationsForTemplateResponse, GetTcbResponse} from '../api';
import {LanguageServiceAdapter, LSParseConfigHost} from './adapters';
import {CompilerFactory} from './compiler_factory';
@ -200,6 +202,29 @@ export class LanguageService {
return result;
}
getComponentLocationsForTemplate(fileName: string): GetComponentLocationsForTemplateResponse {
return this.withCompiler<GetComponentLocationsForTemplateResponse>((compiler) => {
const components = compiler.getComponentsWithTemplateFile(fileName);
const componentDeclarationLocations: ts.DocumentSpan[] =
Array.from(components.values()).map(c => {
let contextSpan: ts.TextSpan|undefined = undefined;
let textSpan: ts.TextSpan;
if (isNamedClassDeclaration(c)) {
textSpan = ts.createTextSpanFromBounds(c.name.getStart(), c.name.getEnd());
contextSpan = ts.createTextSpanFromBounds(c.getStart(), c.getEnd());
} else {
textSpan = ts.createTextSpanFromBounds(c.getStart(), c.getEnd());
}
return {
fileName: c.getSourceFile().fileName,
textSpan,
contextSpan,
};
});
return componentDeclarationLocations;
});
}
getTcb(fileName: string, position: number): GetTcbResponse {
return this.withCompiler<GetTcbResponse>(compiler => {
const templateInfo = getTemplateInfoAtPosition(fileName, position, compiler);

View File

@ -7,7 +7,9 @@
*/
import * as ts from 'typescript/lib/tsserverlibrary';
import {GetTcbResponse, NgLanguageService} from '../api';
import {GetComponentLocationsForTemplateResponse, GetTcbResponse, NgLanguageService} from '../api';
import {LanguageService} from './language_service';
export function create(info: ts.server.PluginCreateInfo): NgLanguageService {
@ -132,6 +134,14 @@ export function create(info: ts.server.PluginCreateInfo): NgLanguageService {
return ngLS.getTcb(fileName, position);
}
/**
* Given an external template, finds the associated components that use it as a `templateUrl`.
*/
function getComponentLocationsForTemplate(fileName: string):
GetComponentLocationsForTemplateResponse {
return ngLS.getComponentLocationsForTemplate(fileName);
}
return {
...tsLS,
getSemanticDiagnostics,
@ -146,6 +156,7 @@ export function create(info: ts.server.PluginCreateInfo): NgLanguageService {
getCompletionEntrySymbol,
getTcb,
getCompilerOptionsDiagnostics,
getComponentLocationsForTemplate,
};
}

View File

@ -141,6 +141,11 @@ export function create(info: tss.server.PluginCreateInfo): NgLanguageService {
return undefined;
}
function getComponentLocationsForTemplate(fileName: string) {
// Not implemented in VE Language Service
return [];
}
return {
// First clone the original TS language service
...tsLS,
@ -154,5 +159,6 @@ export function create(info: tss.server.PluginCreateInfo): NgLanguageService {
getReferencesAtPosition,
findRenameLocations,
getTcb,
getComponentLocationsForTemplate,
};
}