fix(language-service): Make Definition and QuickInfo compatible with TS LS (#31972)
Now that the Angular LS is a proper tsserver plugin, it does not make sense for it to maintain its own language service API. This is part one of the effort to remove our custom LanguageService interface. This interface is cumbersome because we have to do two transformations: ng def -> ts def -> lsp definition The TS LS interface is more comprehensive, so this allows the Angular LS to return more information. PR Close #31972
This commit is contained in:

committed by
Alex Rickabaugh

parent
e906a4f0d8
commit
a8e2ee1343
@ -6,28 +6,50 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as tss from 'typescript/lib/tsserverlibrary';
|
||||
|
||||
import * as ts from 'typescript'; // used as value and is provided at runtime
|
||||
import {TemplateInfo} from './common';
|
||||
import {locateSymbol} from './locate_symbol';
|
||||
import {Location} from './types';
|
||||
import {Span} from './types';
|
||||
|
||||
export function getDefinition(info: TemplateInfo): Location[]|undefined {
|
||||
const result = locateSymbol(info);
|
||||
return result && result.symbol.definition;
|
||||
}
|
||||
|
||||
export function ngLocationToTsDefinitionInfo(loc: Location): tss.DefinitionInfo {
|
||||
/**
|
||||
* Convert Angular Span to TypeScript TextSpan. Angular Span has 'start' and
|
||||
* 'end' whereas TS TextSpan has 'start' and 'length'.
|
||||
* @param span Angular Span
|
||||
*/
|
||||
function ngSpanToTsTextSpan(span: Span): ts.TextSpan {
|
||||
return {
|
||||
fileName: loc.fileName,
|
||||
textSpan: {
|
||||
start: loc.span.start,
|
||||
length: loc.span.end - loc.span.start,
|
||||
},
|
||||
// TODO(kyliau): Provide more useful info for name, kind and containerKind
|
||||
name: '', // should be name of symbol but we don't have enough information here.
|
||||
kind: tss.ScriptElementKind.unknown,
|
||||
containerName: loc.fileName,
|
||||
containerKind: tss.ScriptElementKind.unknown,
|
||||
start: span.start,
|
||||
length: span.end - span.start,
|
||||
};
|
||||
}
|
||||
|
||||
export function getDefinitionAndBoundSpan(info: TemplateInfo): ts.DefinitionInfoAndBoundSpan|
|
||||
undefined {
|
||||
const symbolInfo = locateSymbol(info);
|
||||
if (!symbolInfo) {
|
||||
return;
|
||||
}
|
||||
const textSpan = ngSpanToTsTextSpan(symbolInfo.span);
|
||||
const {symbol} = symbolInfo;
|
||||
const {container, definition: locations} = symbol;
|
||||
if (!locations || !locations.length) {
|
||||
// symbol.definition is really the locations of the symbol. There could be
|
||||
// more than one. No meaningful info could be provided without any location.
|
||||
return {textSpan};
|
||||
}
|
||||
const containerKind = container ? container.kind : ts.ScriptElementKind.unknown;
|
||||
const containerName = container ? container.name : '';
|
||||
const definitions = locations.map((location) => {
|
||||
return {
|
||||
kind: symbol.kind as ts.ScriptElementKind,
|
||||
name: symbol.name,
|
||||
containerKind: containerKind as ts.ScriptElementKind,
|
||||
containerName: containerName,
|
||||
textSpan: ngSpanToTsTextSpan(location.span),
|
||||
fileName: location.fileName,
|
||||
};
|
||||
});
|
||||
return {
|
||||
definitions, textSpan,
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user