Keen Yee Liau 6d11154652 refactor(language-service): Remove redudant 'TemplateInfo' type (#32250)
The TemplateInfo type is an extension of AstResult, but it is not
necessary at all. Instead, improve the current interface for AstResult
by removing all optional fileds and include the TemplateSource in
AstResult instead.

PR Close #32250
2019-08-22 12:32:41 -07:00

62 lines
1.9 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript'; // used as value and is provided at runtime
import {AstResult} from './common';
import {locateSymbol} from './locate_symbol';
import {Span} from './types';
/**
* 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 {
start: span.start,
length: span.end - span.start,
};
}
/**
* Traverse the template AST and look for the symbol located at `position`, then
* return its definition and span of bound text.
* @param info
* @param position
*/
export function getDefinitionAndBoundSpan(
info: AstResult, position: number): ts.DefinitionInfoAndBoundSpan|undefined {
const symbolInfo = locateSymbol(info, position);
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,
};
}