fix(language-service): Update types for TypeScript nullability support
This commit is contained in:
parent
6f5fccfeb7
commit
540581da3e
|
@ -111,7 +111,7 @@ class _Visitor implements html.Visitor {
|
|||
this._translations = translations;
|
||||
|
||||
// Construct a single fake root element
|
||||
const wrapper = new html.Element('wrapper', [], nodes, undefined, undefined, undefined);
|
||||
const wrapper = new html.Element('wrapper', [], nodes, undefined !, undefined, undefined);
|
||||
|
||||
const translatedNode = wrapper.visit(this, null);
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
import {ParseSourceSpan} from '../parse_util';
|
||||
|
||||
export interface Node {
|
||||
sourceSpan: ParseSourceSpan|null;
|
||||
sourceSpan: ParseSourceSpan;
|
||||
visit(visitor: Visitor, context: any): any;
|
||||
}
|
||||
|
||||
export class Text implements Node {
|
||||
constructor(public value: string, public sourceSpan: ParseSourceSpan|null) {}
|
||||
constructor(public value: string, public sourceSpan: ParseSourceSpan) {}
|
||||
visit(visitor: Visitor, context: any): any { return visitor.visitText(this, context); }
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,7 @@ export class Attribute implements Node {
|
|||
export class Element implements Node {
|
||||
constructor(
|
||||
public name: string, public attrs: Attribute[], public children: Node[],
|
||||
public sourceSpan: ParseSourceSpan|null = null,
|
||||
public startSourceSpan: ParseSourceSpan|null = null,
|
||||
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan|null = null,
|
||||
public endSourceSpan: ParseSourceSpan|null = null) {}
|
||||
visit(visitor: Visitor, context: any): any { return visitor.visitElement(this, context); }
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ export interface TemplateAst {
|
|||
/**
|
||||
* The source span from which this node was parsed.
|
||||
*/
|
||||
sourceSpan: ParseSourceSpan|null;
|
||||
sourceSpan: ParseSourceSpan;
|
||||
|
||||
/**
|
||||
* Visit this node and possibly transform it.
|
||||
|
@ -127,7 +127,7 @@ export class ElementAst implements TemplateAst {
|
|||
public directives: DirectiveAst[], public providers: ProviderAst[],
|
||||
public hasViewContainer: boolean, public queryMatches: QueryMatch[],
|
||||
public children: TemplateAst[], public ngContentIndex: number|null,
|
||||
public sourceSpan: ParseSourceSpan|null, public endSourceSpan: ParseSourceSpan|null) {}
|
||||
public sourceSpan: ParseSourceSpan, public endSourceSpan: ParseSourceSpan|null) {}
|
||||
|
||||
visit(visitor: TemplateAstVisitor, context: any): any {
|
||||
return visitor.visitElement(this, context);
|
||||
|
|
|
@ -391,7 +391,7 @@ class TemplateParseVisitor implements html.Visitor {
|
|||
nodeName, attrs, elementProps, events, references,
|
||||
providerContext.transformedDirectiveAsts, providerContext.transformProviders,
|
||||
providerContext.transformedHasViewContainer, providerContext.queryMatches, children,
|
||||
hasInlineTemplates ? null : ngContentIndex, element.sourceSpan || null,
|
||||
hasInlineTemplates ? null : ngContentIndex, element.sourceSpan,
|
||||
element.endSourceSpan || null);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,5 +25,5 @@ export class AstPath<T> {
|
|||
|
||||
push(node: T) { this.path.push(node); }
|
||||
|
||||
pop(): T { return this.path.pop(); }
|
||||
pop(): T { return this.path.pop() !; }
|
||||
}
|
||||
|
|
|
@ -29,27 +29,27 @@ const hiddenHtmlElements = {
|
|||
link: true,
|
||||
};
|
||||
|
||||
export function getTemplateCompletions(templateInfo: TemplateInfo): Completions {
|
||||
let result: Completions = undefined;
|
||||
export function getTemplateCompletions(templateInfo: TemplateInfo): Completions|undefined {
|
||||
let result: Completions|undefined = undefined;
|
||||
let {htmlAst, templateAst, template} = templateInfo;
|
||||
// The templateNode starts at the delimiter character so we add 1 to skip it.
|
||||
let templatePosition = templateInfo.position - template.span.start;
|
||||
let templatePosition = templateInfo.position ! - template.span.start;
|
||||
let path = new HtmlAstPath(htmlAst, templatePosition);
|
||||
let mostSpecific = path.tail;
|
||||
if (path.empty) {
|
||||
result = elementCompletions(templateInfo, path);
|
||||
} else {
|
||||
let astPosition = templatePosition - mostSpecific.sourceSpan.start.offset;
|
||||
mostSpecific.visit(
|
||||
let astPosition = templatePosition - mostSpecific !.sourceSpan !.start.offset;
|
||||
mostSpecific !.visit(
|
||||
{
|
||||
visitElement(ast) {
|
||||
let startTagSpan = spanOf(ast.sourceSpan);
|
||||
let tagLen = ast.name.length;
|
||||
if (templatePosition <=
|
||||
startTagSpan.start + tagLen + 1 /* 1 for the opening angle bracked */) {
|
||||
startTagSpan !.start + tagLen + 1 /* 1 for the opening angle bracked */) {
|
||||
// If we are in the tag then return the element completions.
|
||||
result = elementCompletions(templateInfo, path);
|
||||
} else if (templatePosition < startTagSpan.end) {
|
||||
} else if (templatePosition < startTagSpan !.end) {
|
||||
// We are in the attribute section of the element (but not in an attribute).
|
||||
// Return the attribute completions.
|
||||
result = attributeCompletions(templateInfo, path);
|
||||
|
@ -65,7 +65,7 @@ export function getTemplateCompletions(templateInfo: TemplateInfo): Completions
|
|||
},
|
||||
visitText(ast) {
|
||||
// Check if we are in a entity.
|
||||
result = entityCompletions(getSourceText(template, spanOf(ast)), astPosition);
|
||||
result = entityCompletions(getSourceText(template, spanOf(ast) !), astPosition);
|
||||
if (result) return result;
|
||||
result = interpolationCompletions(templateInfo, templatePosition);
|
||||
if (result) return result;
|
||||
|
@ -96,8 +96,8 @@ export function getTemplateCompletions(templateInfo: TemplateInfo): Completions
|
|||
return result;
|
||||
}
|
||||
|
||||
function attributeCompletions(info: TemplateInfo, path: HtmlAstPath): Completions {
|
||||
let item = path.tail instanceof Element ? path.tail : path.parentOf(path.tail);
|
||||
function attributeCompletions(info: TemplateInfo, path: HtmlAstPath): Completions|undefined {
|
||||
let item = path.tail instanceof Element ? path.tail : path.parentOf(path.tail !);
|
||||
if (item instanceof Element) {
|
||||
return attributeCompletionsForElement(info, item.name, item);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ function getAttributeInfosForElement(
|
|||
const selectorAndAttributeNames =
|
||||
applicableSelectors.map(selector => ({selector, attrs: selector.attrs.filter(a => !!a)}));
|
||||
let attrs = flatten(selectorAndAttributeNames.map<AttrInfo[]>(selectorAndAttr => {
|
||||
const directive = selectorMap.get(selectorAndAttr.selector);
|
||||
const directive = selectorMap.get(selectorAndAttr.selector) !;
|
||||
const result = selectorAndAttr.attrs.map<AttrInfo>(
|
||||
name => ({name, input: name in directive.inputs, output: name in directive.outputs}));
|
||||
return result;
|
||||
|
@ -165,7 +165,7 @@ function getAttributeInfosForElement(
|
|||
// All input and output properties of the matching directives should be added.
|
||||
let elementSelector = element ?
|
||||
createElementCssSelector(element) :
|
||||
createElementCssSelector(new Element(elementName, [], [], undefined, undefined, undefined));
|
||||
createElementCssSelector(new Element(elementName, [], [], null !, null, null));
|
||||
|
||||
let matcher = new SelectorMatcher();
|
||||
matcher.addSelectables(selectors);
|
||||
|
@ -188,7 +188,7 @@ function getAttributeInfosForElement(
|
|||
}
|
||||
|
||||
function attributeValueCompletions(
|
||||
info: TemplateInfo, position: number, attr: Attribute): Completions {
|
||||
info: TemplateInfo, position: number, attr: Attribute): Completions|undefined {
|
||||
const path = new TemplateAstPath(info.templateAst, position);
|
||||
const mostSpecific = path.tail;
|
||||
if (mostSpecific) {
|
||||
|
@ -209,7 +209,7 @@ function attributeValueCompletions(
|
|||
}
|
||||
}
|
||||
|
||||
function elementCompletions(info: TemplateInfo, path: HtmlAstPath): Completions {
|
||||
function elementCompletions(info: TemplateInfo, path: HtmlAstPath): Completions|undefined {
|
||||
let htmlNames = elementNames().filter(name => !(name in hiddenHtmlElements));
|
||||
|
||||
// Collect the elements referenced by the selectors
|
||||
|
@ -217,18 +217,18 @@ function elementCompletions(info: TemplateInfo, path: HtmlAstPath): Completions
|
|||
getSelectors(info).selectors.map(selector => selector.element).filter(name => !!name);
|
||||
|
||||
let components =
|
||||
directiveElements.map<Completion>(name => ({kind: 'component', name: name, sort: name}));
|
||||
directiveElements.map<Completion>(name => ({kind: 'component', name: name !, sort: name !}));
|
||||
let htmlElements = htmlNames.map<Completion>(name => ({kind: 'element', name: name, sort: name}));
|
||||
|
||||
// Return components and html elements
|
||||
return uniqueByName(htmlElements.concat(components));
|
||||
}
|
||||
|
||||
function entityCompletions(value: string, position: number): Completions {
|
||||
function entityCompletions(value: string, position: number): Completions|undefined {
|
||||
// Look for entity completions
|
||||
const re = /&[A-Za-z]*;?(?!\d)/g;
|
||||
let found: RegExpExecArray|null;
|
||||
let result: Completions;
|
||||
let result: Completions|undefined = undefined;
|
||||
while (found = re.exec(value)) {
|
||||
let len = found[0].length;
|
||||
if (position >= found.index && position < (found.index + len)) {
|
||||
|
@ -240,7 +240,7 @@ function entityCompletions(value: string, position: number): Completions {
|
|||
return result;
|
||||
}
|
||||
|
||||
function interpolationCompletions(info: TemplateInfo, position: number): Completions {
|
||||
function interpolationCompletions(info: TemplateInfo, position: number): Completions|undefined {
|
||||
// Look for an interpolation in at the position.
|
||||
const templatePath = new TemplateAstPath(info.templateAst, position);
|
||||
const mostSpecific = templatePath.tail;
|
||||
|
@ -258,13 +258,14 @@ function interpolationCompletions(info: TemplateInfo, position: number): Complet
|
|||
// the attributes of an "a" element, not requesting completion in the a text element. This
|
||||
// code checks for this case and returns element completions if it is detected or undefined
|
||||
// if it is not.
|
||||
function voidElementAttributeCompletions(info: TemplateInfo, path: HtmlAstPath): Completions {
|
||||
function voidElementAttributeCompletions(info: TemplateInfo, path: HtmlAstPath): Completions|
|
||||
undefined {
|
||||
let tail = path.tail;
|
||||
if (tail instanceof Text) {
|
||||
let match = tail.value.match(/<(\w(\w|\d|-)*:)?(\w(\w|\d|-)*)\s/);
|
||||
let match = tail.value.match(/<(\w(\w|\d|-)*:)?(\w(\w|\d|-)*)\s/) !;
|
||||
// The position must be after the match, otherwise we are still in a place where elements
|
||||
// are expected (such as `<|a` or `<a|`; we only want attributes for `<a |` or after).
|
||||
if (match && path.position >= match.index + match[0].length + tail.sourceSpan.start.offset) {
|
||||
if (match && path.position >= match.index ! + match[0].length + tail.sourceSpan.start.offset) {
|
||||
return attributeCompletionsForElement(info, match[3]);
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +311,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
|||
this.info.expressionParser.parseTemplateBindings(key, this.attr.value, null);
|
||||
|
||||
// find the template binding that contains the position
|
||||
const valueRelativePosition = this.position - this.attr.valueSpan.start.offset - 1;
|
||||
const valueRelativePosition = this.position - this.attr.valueSpan !.start.offset - 1;
|
||||
const bindings = templateBindingResult.templateBindings;
|
||||
const binding =
|
||||
bindings.find(
|
||||
|
@ -340,7 +341,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
|||
// template reference's type parameter.
|
||||
const directiveMetadata = selectorInfo.map.get(selector);
|
||||
const contextTable =
|
||||
this.info.template.query.getTemplateContext(directiveMetadata.type.reference);
|
||||
this.info.template.query.getTemplateContext(directiveMetadata !.type.reference);
|
||||
if (contextTable) {
|
||||
this.result = this.symbolsToCompletions(contextTable.values());
|
||||
}
|
||||
|
@ -370,7 +371,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
|||
const expressionPosition = this.position - ast.sourceSpan.start.offset;
|
||||
if (inSpan(expressionPosition, ast.value.span)) {
|
||||
const completions = getExpressionCompletions(
|
||||
this.getExpressionScope(), ast.value, expressionPosition, this.info.template.query);
|
||||
this.getExpressionScope !(), ast.value, expressionPosition, this.info.template.query);
|
||||
if (completions) {
|
||||
this.result = this.symbolsToCompletions(completions);
|
||||
}
|
||||
|
@ -379,8 +380,8 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
|||
|
||||
private attributeValueCompletions(value: AST, position?: number) {
|
||||
const symbols = getExpressionCompletions(
|
||||
this.getExpressionScope(), value, position == null ? this.attributeValuePosition : position,
|
||||
this.info.template.query);
|
||||
this.getExpressionScope !(), value,
|
||||
position == null ? this.attributeValuePosition : position, this.info.template.query);
|
||||
if (symbols) {
|
||||
this.result = this.symbolsToCompletions(symbols);
|
||||
}
|
||||
|
@ -392,7 +393,7 @@ class ExpressionVisitor extends NullTemplateVisitor {
|
|||
}
|
||||
|
||||
private get attributeValuePosition() {
|
||||
return this.position - this.attr.valueSpan.start.offset - 1;
|
||||
return this.position - this.attr !.valueSpan !.start.offset - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ export function getTemplateDiagnostics(
|
|||
results.push(...ast.parseErrors.map<Diagnostic>(
|
||||
e => ({
|
||||
kind: DiagnosticKind.Error,
|
||||
span: offsetSpan(spanOf(e.span), template.span.start),
|
||||
span: offsetSpan(spanOf(e.span) !, template.span.start),
|
||||
message: e.msg
|
||||
})));
|
||||
} else if (ast.templateAst) {
|
||||
|
@ -66,7 +66,8 @@ export function getDeclarationDiagnostics(
|
|||
report(
|
||||
`Component '${declaration.type.name}' is not included in a module and will not be available inside a template. Consider adding it to a NgModule declaration`);
|
||||
}
|
||||
if (!declaration.metadata.template.template && !declaration.metadata.template.templateUrl) {
|
||||
if (!declaration.metadata.template !.template &&
|
||||
!declaration.metadata.template !.templateUrl) {
|
||||
report(`Component ${declaration.type.name} must have a template or templateUrl`);
|
||||
}
|
||||
} else {
|
||||
|
@ -74,7 +75,7 @@ export function getDeclarationDiagnostics(
|
|||
directives = new Set();
|
||||
modules.ngModules.forEach(module => {
|
||||
module.declaredDirectives.forEach(
|
||||
directive => { directives.add(directive.reference); });
|
||||
directive => { directives !.add(directive.reference); });
|
||||
});
|
||||
}
|
||||
if (!directives.has(declaration.type)) {
|
||||
|
@ -92,17 +93,17 @@ function getTemplateExpressionDiagnostics(
|
|||
template: TemplateSource, astResult: AstResult): Diagnostics {
|
||||
const info: TemplateInfo = {
|
||||
template,
|
||||
htmlAst: astResult.htmlAst,
|
||||
directive: astResult.directive,
|
||||
directives: astResult.directives,
|
||||
pipes: astResult.pipes,
|
||||
templateAst: astResult.templateAst,
|
||||
expressionParser: astResult.expressionParser
|
||||
htmlAst: astResult.htmlAst !,
|
||||
directive: astResult.directive !,
|
||||
directives: astResult.directives !,
|
||||
pipes: astResult.pipes !,
|
||||
templateAst: astResult.templateAst !,
|
||||
expressionParser: astResult.expressionParser !
|
||||
};
|
||||
const visitor = new ExpressionDiagnosticsVisitor(
|
||||
info, (path: TemplateAstPath, includeEvent: boolean) =>
|
||||
getExpressionScope(info, path, includeEvent));
|
||||
templateVisitAll(visitor, astResult.templateAst);
|
||||
templateVisitAll(visitor, astResult.templateAst !);
|
||||
return visitor.diagnostics;
|
||||
}
|
||||
|
||||
|
@ -153,15 +154,15 @@ class ExpressionDiagnosticsVisitor extends TemplateAstChildVisitor {
|
|||
visitVariable(ast: VariableAst): void {
|
||||
const directive = this.directiveSummary;
|
||||
if (directive && ast.value) {
|
||||
const context = this.info.template.query.getTemplateContext(directive.type.reference);
|
||||
const context = this.info.template.query.getTemplateContext(directive.type.reference) !;
|
||||
if (context && !context.has(ast.value)) {
|
||||
if (ast.value === '$implicit') {
|
||||
this.reportError(
|
||||
'The template context does not have an implicit value', spanOf(ast.sourceSpan));
|
||||
'The template context does not have an implicit value', spanOf(ast.sourceSpan) !);
|
||||
} else {
|
||||
this.reportError(
|
||||
`The template context does not defined a member called '${ast.value}'`,
|
||||
spanOf(ast.sourceSpan));
|
||||
spanOf(ast.sourceSpan) !);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +181,7 @@ class ExpressionDiagnosticsVisitor extends TemplateAstChildVisitor {
|
|||
|
||||
// Find directive that refernces this template
|
||||
this.directiveSummary =
|
||||
ast.directives.map(d => d.directive).find(d => hasTemplateReference(d.type));
|
||||
ast.directives.map(d => d.directive).find(d => hasTemplateReference(d.type)) !;
|
||||
|
||||
// Process children
|
||||
super.visitEmbeddedTemplate(ast, context);
|
||||
|
@ -225,7 +226,7 @@ class ExpressionDiagnosticsVisitor extends TemplateAstChildVisitor {
|
|||
return result;
|
||||
}
|
||||
|
||||
private findElement(position: number): Element {
|
||||
private findElement(position: number): Element|undefined {
|
||||
const htmlPath = new HtmlAstPath(this.info.htmlAst, position);
|
||||
if (htmlPath.tail instanceof Element) {
|
||||
return htmlPath.tail;
|
||||
|
|
|
@ -25,10 +25,10 @@ export function getExpressionDiagnostics(
|
|||
}
|
||||
|
||||
export function getExpressionCompletions(
|
||||
scope: SymbolTable, ast: AST, position: number, query: SymbolQuery): Symbol[] {
|
||||
scope: SymbolTable, ast: AST, position: number, query: SymbolQuery): Symbol[]|undefined {
|
||||
const path = new AstPath(ast, position);
|
||||
if (path.empty) return undefined;
|
||||
const tail = path.tail;
|
||||
const tail = path.tail !;
|
||||
let result: SymbolTable|undefined = scope;
|
||||
|
||||
function getType(ast: AST): Symbol { return new AstType(scope, query, {}).getType(ast); }
|
||||
|
@ -84,15 +84,15 @@ export function getExpressionCompletions(
|
|||
|
||||
export function getExpressionSymbol(
|
||||
scope: SymbolTable, ast: AST, position: number,
|
||||
query: SymbolQuery): {symbol: Symbol, span: Span} {
|
||||
query: SymbolQuery): {symbol: Symbol, span: Span}|undefined {
|
||||
const path = new AstPath(ast, position, /* excludeEmpty */ true);
|
||||
if (path.empty) return undefined;
|
||||
const tail = path.tail;
|
||||
const tail = path.tail !;
|
||||
|
||||
function getType(ast: AST): Symbol { return new AstType(scope, query, {}).getType(ast); }
|
||||
|
||||
let symbol: Symbol = undefined;
|
||||
let span: Span = undefined;
|
||||
let symbol: Symbol|undefined = undefined;
|
||||
let span: Span|undefined = undefined;
|
||||
|
||||
// If the completion request is in a not in a pipe or property access then the global scope
|
||||
// (that is the scope of the implicit receiver) is the right scope as the user is typing the
|
||||
|
@ -340,7 +340,7 @@ class AstType implements ExpressionVisitor {
|
|||
// support contextual typing of arguments so this is simpler than TypeScript's
|
||||
// version.
|
||||
const args = ast.args.map(arg => this.getType(arg));
|
||||
const target = this.getType(ast.target);
|
||||
const target = this.getType(ast.target !);
|
||||
if (!target || !target.callable) return this.reportError('Call target is not callable', ast);
|
||||
const signature = target.selectSignature(args);
|
||||
if (signature) return signature.result;
|
||||
|
@ -434,7 +434,7 @@ class AstType implements ExpressionVisitor {
|
|||
// The type of a pipe node is the return type of the pipe's transform method. The table returned
|
||||
// by getPipes() is expected to contain symbols with the corresponding transform method type.
|
||||
const pipe = this.query.getPipes().get(ast.name);
|
||||
if (!pipe) return this.reportError(`No pipe by the name ${pipe.name} found`, ast);
|
||||
if (!pipe) return this.reportError(`No pipe by the name ${ast.name} found`, ast);
|
||||
const expType = this.getType(ast.exp);
|
||||
const signature =
|
||||
pipe.selectSignature([expType].concat(ast.args.map(arg => this.getType(arg))));
|
||||
|
@ -495,8 +495,8 @@ class AstType implements ExpressionVisitor {
|
|||
// The type of a method is the selected methods result type.
|
||||
const method = receiverType.members().get(ast.name);
|
||||
if (!method) return this.reportError(`Unknown method ${ast.name}`, ast);
|
||||
if (!method.type.callable) return this.reportError(`Member ${ast.name} is not callable`, ast);
|
||||
const signature = method.type.selectSignature(ast.args.map(arg => this.getType(arg)));
|
||||
if (!method.type !.callable) return this.reportError(`Member ${ast.name} is not callable`, ast);
|
||||
const signature = method.type !.selectSignature(ast.args.map(arg => this.getType(arg)));
|
||||
if (!signature)
|
||||
return this.reportError(`Unable to resolve signature for call of method ${ast.name}`, ast);
|
||||
return signature.result;
|
||||
|
@ -550,7 +550,7 @@ class AstType implements ExpressionVisitor {
|
|||
|
||||
private isAny(symbol: Symbol): boolean {
|
||||
return !symbol || this.query.getTypeKind(symbol) == BuiltinType.Any ||
|
||||
(symbol.type && this.isAny(symbol.type));
|
||||
(!!symbol.type && this.isAny(symbol.type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,7 +601,7 @@ function visitChildren(ast: AST, visitor: ExpressionVisitor) {
|
|||
visit(ast.falseExp);
|
||||
},
|
||||
visitFunctionCall(ast) {
|
||||
visit(ast.target);
|
||||
visit(ast.target !);
|
||||
visitAll(ast.args);
|
||||
},
|
||||
visitImplicitReceiver(ast) {},
|
||||
|
@ -676,7 +676,7 @@ function getReferences(info: TemplateInfo): SymbolDeclaration[] {
|
|||
|
||||
function processReferences(references: ReferenceAst[]) {
|
||||
for (const reference of references) {
|
||||
let type: Symbol;
|
||||
let type: Symbol = undefined !;
|
||||
if (reference.value) {
|
||||
type = info.template.query.getTypeSymbol(tokenReference(reference.value));
|
||||
}
|
||||
|
@ -721,11 +721,11 @@ function getVarDeclarations(info: TemplateInfo, path: TemplateAstPath): SymbolDe
|
|||
.find(c => !!c);
|
||||
|
||||
// Determine the type of the context field referenced by variable.value.
|
||||
let type: Symbol;
|
||||
let type: Symbol = undefined !;
|
||||
if (context) {
|
||||
const value = context.get(variable.value);
|
||||
if (value) {
|
||||
type = value.type;
|
||||
type = value.type !;
|
||||
let kind = info.template.query.getTypeKind(type);
|
||||
if (kind === BuiltinType.Any || kind == BuiltinType.Unbound) {
|
||||
// The any type is not very useful here. For special cases, such as ngFor, we can do
|
||||
|
@ -762,7 +762,7 @@ function refinedVariableType(
|
|||
const bindingType =
|
||||
new AstType(info.template.members, info.template.query, {}).getType(ngForOfBinding.value);
|
||||
if (bindingType) {
|
||||
return info.template.query.getElementType(bindingType);
|
||||
return info.template.query.getElementType(bindingType) !;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -771,7 +771,7 @@ function refinedVariableType(
|
|||
return type;
|
||||
}
|
||||
|
||||
function getDefintionOf(info: TemplateInfo, ast: TemplateAst): Definition {
|
||||
function getDefintionOf(info: TemplateInfo, ast: TemplateAst): Definition|undefined {
|
||||
if (info.fileName) {
|
||||
const templateOffset = info.template.span.start;
|
||||
return [{
|
||||
|
|
|
@ -10,7 +10,7 @@ import {TemplateInfo} from './common';
|
|||
import {locateSymbol} from './locate_symbol';
|
||||
import {Hover, HoverTextSection, Symbol} from './types';
|
||||
|
||||
export function getHover(info: TemplateInfo): Hover {
|
||||
export function getHover(info: TemplateInfo): Hover|undefined {
|
||||
const result = locateSymbol(info);
|
||||
if (result) {
|
||||
return {text: hoverTextOf(result.symbol), span: result.span};
|
||||
|
|
|
@ -59,7 +59,7 @@ class HtmlAstPathBuilder extends ChildVisitor {
|
|||
constructor(private position: number) { super(); }
|
||||
|
||||
visit(ast: Node, context: any): any {
|
||||
let span = spanOf(ast);
|
||||
let span = spanOf(ast as any);
|
||||
if (inSpan(this.position, span)) {
|
||||
this.path.push(ast);
|
||||
} else {
|
||||
|
|
|
@ -32,7 +32,7 @@ class LanguageServiceImpl implements LanguageService {
|
|||
|
||||
getTemplateReferences(): string[] { return this.host.getTemplateReferences(); }
|
||||
|
||||
getDiagnostics(fileName: string): Diagnostics {
|
||||
getDiagnostics(fileName: string): Diagnostics|undefined {
|
||||
let results: Diagnostics = [];
|
||||
let templates = this.host.getTemplates(fileName);
|
||||
if (templates && templates.length) {
|
||||
|
@ -70,14 +70,14 @@ class LanguageServiceImpl implements LanguageService {
|
|||
}
|
||||
}
|
||||
|
||||
getHoverAt(fileName: string, position: number): Hover {
|
||||
getHoverAt(fileName: string, position: number): Hover|undefined {
|
||||
let templateInfo = this.getTemplateAstAtPosition(fileName, position);
|
||||
if (templateInfo) {
|
||||
return getHover(templateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private getTemplateAstAtPosition(fileName: string, position: number): TemplateInfo {
|
||||
private getTemplateAstAtPosition(fileName: string, position: number): TemplateInfo|undefined {
|
||||
let template = this.host.getTemplateAt(fileName, position);
|
||||
if (template) {
|
||||
let astResult = this.getTemplateAst(template, fileName);
|
||||
|
@ -87,18 +87,18 @@ class LanguageServiceImpl implements LanguageService {
|
|||
fileName,
|
||||
template,
|
||||
htmlAst: astResult.htmlAst,
|
||||
directive: astResult.directive,
|
||||
directives: astResult.directives,
|
||||
pipes: astResult.pipes,
|
||||
directive: astResult.directive !,
|
||||
directives: astResult.directives !,
|
||||
pipes: astResult.pipes !,
|
||||
templateAst: astResult.templateAst,
|
||||
expressionParser: astResult.expressionParser
|
||||
expressionParser: astResult.expressionParser !
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getTemplateAst(template: TemplateSource, contextFile: string): AstResult {
|
||||
let result: AstResult;
|
||||
let result: AstResult = undefined !;
|
||||
try {
|
||||
const resolvedMetadata =
|
||||
this.metadataResolver.getNonNormalizedDirectiveMetadata(template.type as any);
|
||||
|
@ -109,10 +109,10 @@ class LanguageServiceImpl implements LanguageService {
|
|||
const expressionParser = new Parser(new Lexer());
|
||||
const config = new CompilerConfig();
|
||||
const parser = new TemplateParser(
|
||||
config, expressionParser, new DomElementSchemaRegistry(), htmlParser, null, []);
|
||||
config, expressionParser, new DomElementSchemaRegistry(), htmlParser, null !, []);
|
||||
const htmlResult = htmlParser.parse(template.source, '', true);
|
||||
const analyzedModules = this.host.getAnalyzedModules();
|
||||
let errors: Diagnostic[] = undefined;
|
||||
let errors: Diagnostic[] = undefined !;
|
||||
let ngModule = analyzedModules.ngModuleByPipeOrDirective.get(template.type);
|
||||
if (!ngModule) {
|
||||
// Reported by the the declaration diagnostics.
|
||||
|
@ -122,7 +122,7 @@ class LanguageServiceImpl implements LanguageService {
|
|||
const resolvedDirectives = ngModule.transitiveModule.directives.map(
|
||||
d => this.host.resolver.getNonNormalizedDirectiveMetadata(d.reference));
|
||||
const directives =
|
||||
resolvedDirectives.filter(d => d !== null).map(d => d.metadata.toSummary());
|
||||
resolvedDirectives.filter(d => d !== null).map(d => d !.metadata.toSummary());
|
||||
const pipes = ngModule.transitiveModule.pipes.map(
|
||||
p => this.host.resolver.getOrLoadPipeMetadata(p.reference).toSummary());
|
||||
const schemas = ngModule.schemas;
|
||||
|
@ -171,7 +171,7 @@ function uniqueBySpan < T extends {
|
|||
}
|
||||
|
||||
function findSuitableDefaultModule(modules: NgAnalyzedModules): CompileNgModuleMetadata {
|
||||
let result: CompileNgModuleMetadata;
|
||||
let result: CompileNgModuleMetadata = undefined !;
|
||||
let resultSize = 0;
|
||||
for (const module of modules.ngModules) {
|
||||
const moduleSize = module.transitiveModule.directives.length;
|
||||
|
|
|
@ -20,18 +20,18 @@ export interface SymbolInfo {
|
|||
span: Span;
|
||||
}
|
||||
|
||||
export function locateSymbol(info: TemplateInfo): SymbolInfo {
|
||||
const templatePosition = info.position - info.template.span.start;
|
||||
export function locateSymbol(info: TemplateInfo): SymbolInfo|undefined {
|
||||
const templatePosition = info.position ! - info.template.span.start;
|
||||
const path = new TemplateAstPath(info.templateAst, templatePosition);
|
||||
if (path.tail) {
|
||||
let symbol: Symbol = undefined;
|
||||
let span: Span = undefined;
|
||||
let symbol: Symbol = undefined !;
|
||||
let span: Span = undefined !;
|
||||
const attributeValueSymbol = (ast: AST, inEvent: boolean = false): boolean => {
|
||||
const attribute = findAttribute(info);
|
||||
if (attribute) {
|
||||
if (inSpan(templatePosition, spanOf(attribute.valueSpan))) {
|
||||
const scope = getExpressionScope(info, path, inEvent);
|
||||
const expressionOffset = attribute.valueSpan.start.offset + 1;
|
||||
const expressionOffset = attribute.valueSpan !.start.offset + 1;
|
||||
const result = getExpressionSymbol(
|
||||
scope, ast, templatePosition - expressionOffset, info.template.query);
|
||||
if (result) {
|
||||
|
@ -52,28 +52,28 @@ export function locateSymbol(info: TemplateInfo): SymbolInfo {
|
|||
if (component) {
|
||||
symbol = info.template.query.getTypeSymbol(component.directive.type.reference);
|
||||
symbol = symbol && new OverrideKindSymbol(symbol, 'component');
|
||||
span = spanOf(ast);
|
||||
span = spanOf(ast) !;
|
||||
} else {
|
||||
// Find a directive that matches the element name
|
||||
const directive =
|
||||
ast.directives.find(d => d.directive.selector.indexOf(ast.name) >= 0);
|
||||
ast.directives.find(d => d.directive.selector !.indexOf(ast.name) >= 0);
|
||||
if (directive) {
|
||||
symbol = info.template.query.getTypeSymbol(directive.directive.type.reference);
|
||||
symbol = symbol && new OverrideKindSymbol(symbol, 'directive');
|
||||
span = spanOf(ast);
|
||||
span = spanOf(ast) !;
|
||||
}
|
||||
}
|
||||
},
|
||||
visitReference(ast) {
|
||||
symbol = info.template.query.getTypeSymbol(tokenReference(ast.value));
|
||||
span = spanOf(ast);
|
||||
span = spanOf(ast) !;
|
||||
},
|
||||
visitVariable(ast) {},
|
||||
visitEvent(ast) {
|
||||
if (!attributeValueSymbol(ast.handler, /* inEvent */ true)) {
|
||||
symbol = findOutputBinding(info, path, ast);
|
||||
symbol = findOutputBinding(info, path, ast) !;
|
||||
symbol = symbol && new OverrideKindSymbol(symbol, 'event');
|
||||
span = spanOf(ast);
|
||||
span = spanOf(ast) !;
|
||||
}
|
||||
},
|
||||
visitElementProperty(ast) { attributeValueSymbol(ast.value); },
|
||||
|
@ -93,12 +93,12 @@ export function locateSymbol(info: TemplateInfo): SymbolInfo {
|
|||
visitText(ast) {},
|
||||
visitDirective(ast) {
|
||||
symbol = info.template.query.getTypeSymbol(ast.directive.type.reference);
|
||||
span = spanOf(ast);
|
||||
span = spanOf(ast) !;
|
||||
},
|
||||
visitDirectiveProperty(ast) {
|
||||
if (!attributeValueSymbol(ast.value)) {
|
||||
symbol = findInputBinding(info, path, ast);
|
||||
span = spanOf(ast);
|
||||
symbol = findInputBinding(info, path, ast) !;
|
||||
span = spanOf(ast) !;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -109,14 +109,15 @@ export function locateSymbol(info: TemplateInfo): SymbolInfo {
|
|||
}
|
||||
}
|
||||
|
||||
function findAttribute(info: TemplateInfo): Attribute {
|
||||
const templatePosition = info.position - info.template.span.start;
|
||||
function findAttribute(info: TemplateInfo): Attribute|undefined {
|
||||
const templatePosition = info.position ! - info.template.span.start;
|
||||
const path = new HtmlAstPath(info.htmlAst, templatePosition);
|
||||
return path.first(Attribute);
|
||||
}
|
||||
|
||||
function findInputBinding(
|
||||
info: TemplateInfo, path: TemplateAstPath, binding: BoundDirectivePropertyAst): Symbol {
|
||||
info: TemplateInfo, path: TemplateAstPath, binding: BoundDirectivePropertyAst): Symbol|
|
||||
undefined {
|
||||
const element = path.first(ElementAst);
|
||||
if (element) {
|
||||
for (const directive of element.directives) {
|
||||
|
@ -133,7 +134,7 @@ function findInputBinding(
|
|||
}
|
||||
|
||||
function findOutputBinding(
|
||||
info: TemplateInfo, path: TemplateAstPath, binding: BoundEventAst): Symbol {
|
||||
info: TemplateInfo, path: TemplateAstPath, binding: BoundEventAst): Symbol|undefined {
|
||||
const element = path.first(ElementAst);
|
||||
if (element) {
|
||||
for (const directive of element.directives) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import * as ts from 'typescript';
|
|||
class ReflectorModuleModuleResolutionHost implements ts.ModuleResolutionHost {
|
||||
constructor(private host: ts.LanguageServiceHost) {
|
||||
if (host.directoryExists)
|
||||
this.directoryExists = directoryName => this.host.directoryExists(directoryName);
|
||||
this.directoryExists = directoryName => this.host.directoryExists !(directoryName);
|
||||
}
|
||||
|
||||
fileExists(fileName: string): boolean { return !!this.host.getScriptSnapshot(fileName); }
|
||||
|
@ -22,6 +22,7 @@ class ReflectorModuleModuleResolutionHost implements ts.ModuleResolutionHost {
|
|||
if (snapshot) {
|
||||
return snapshot.getText(0, snapshot.getLength());
|
||||
}
|
||||
return undefined !;
|
||||
}
|
||||
|
||||
directoryExists: (directoryName: string) => boolean;
|
||||
|
@ -32,7 +33,7 @@ export class ReflectorHost extends CompilerHost {
|
|||
private getProgram: () => ts.Program, serviceHost: ts.LanguageServiceHost,
|
||||
options: AngularCompilerOptions) {
|
||||
super(
|
||||
null, options,
|
||||
null !, options,
|
||||
new ModuleResolutionHostAdapter(new ReflectorModuleModuleResolutionHost(serviceHost)),
|
||||
{verboseInvalidExpression: true});
|
||||
}
|
||||
|
|
|
@ -104,10 +104,10 @@ class TemplateAstPathBuilder extends TemplateAstChildVisitor {
|
|||
constructor(private position: number, private allowWidening: boolean) { super(); }
|
||||
|
||||
visit(ast: TemplateAst, context: any): any {
|
||||
let span = spanOf(ast);
|
||||
let span = spanOf(ast) !;
|
||||
if (inSpan(this.position, span)) {
|
||||
const len = this.path.length;
|
||||
if (!len || this.allowWidening || isNarrower(span, spanOf(this.path[len - 1]))) {
|
||||
if (!len || this.allowWidening || isNarrower(span, spanOf(this.path[len - 1]) !)) {
|
||||
this.path.push(ast);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -45,7 +45,7 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
|
|||
}
|
||||
|
||||
const serviceHost = new TypeScriptServiceHost(info.languageServiceHost, info.languageService);
|
||||
const ls = createLanguageService(serviceHost);
|
||||
const ls = createLanguageService(serviceHost as any);
|
||||
serviceHost.setSite(ls);
|
||||
|
||||
proxy.getCompletionsAtPosition = function(fileName: string, position: number) {
|
||||
|
@ -76,7 +76,7 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
|
|||
if (ours) {
|
||||
const displayParts: typeof base.displayParts = [];
|
||||
for (const part of ours.text) {
|
||||
displayParts.push({kind: part.language, text: part.text});
|
||||
displayParts.push({kind: part.language !, text: part.text});
|
||||
}
|
||||
base = {
|
||||
displayParts,
|
||||
|
|
|
@ -84,7 +84,7 @@ export interface TemplateSource {
|
|||
*
|
||||
* @experimental
|
||||
*/
|
||||
export type TemplateSources = TemplateSource[] /* | undefined */;
|
||||
export type TemplateSources = TemplateSource[] | undefined;
|
||||
|
||||
/**
|
||||
* Error information found getting declaration information
|
||||
|
@ -227,7 +227,7 @@ export interface Symbol {
|
|||
/**
|
||||
* A symbol representing type of the symbol.
|
||||
*/
|
||||
readonly type: Symbol /* | undefined */;
|
||||
readonly type: Symbol|undefined;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -235,7 +235,7 @@ export interface Symbol {
|
|||
* is the class or interface of the method. If no container is appropriate, undefined is
|
||||
* returned.
|
||||
*/
|
||||
readonly container: Symbol /* | undefined */;
|
||||
readonly container: Symbol|undefined;
|
||||
|
||||
/**
|
||||
* The symbol is public in the container.
|
||||
|
@ -250,7 +250,7 @@ export interface Symbol {
|
|||
/**
|
||||
* The location of the definition of the symbol
|
||||
*/
|
||||
readonly definition: Definition;
|
||||
readonly definition: Definition|undefined;
|
||||
/**
|
||||
|
||||
* A table of the members of the symbol; that is, the members that can appear
|
||||
|
@ -270,13 +270,13 @@ export interface Symbol {
|
|||
* given the `types` supplied. If no signature would match, this method should
|
||||
* return `undefined`.
|
||||
*/
|
||||
selectSignature(types: Symbol[]): Signature /* | undefined */;
|
||||
selectSignature(types: Symbol[]): Signature|undefined;
|
||||
|
||||
/**
|
||||
* Return the type of the expression if this symbol is indexed by `argument`.
|
||||
* If the symbol cannot be indexed, this method should return `undefined`.
|
||||
*/
|
||||
indexed(argument: Symbol): Symbol /* | undefined */;
|
||||
indexed(argument: Symbol): Symbol|undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -296,7 +296,7 @@ export interface SymbolTable {
|
|||
* Get the symbol corresponding to `key` or `undefined` if there is no symbol in the
|
||||
* table by the name `key`.
|
||||
*/
|
||||
get(key: string): Symbol /* | undefined */;
|
||||
get(key: string): Symbol|undefined;
|
||||
|
||||
/**
|
||||
* Returns `true` if the table contains a `Symbol` with the name `key`.
|
||||
|
@ -364,7 +364,7 @@ export interface SymbolQuery {
|
|||
* Return element type symbol for an array type if the `type` is an array type. Otherwise return
|
||||
* undefined.
|
||||
*/
|
||||
getElementType(type: Symbol): Symbol /* | undefined */;
|
||||
getElementType(type: Symbol): Symbol|undefined;
|
||||
|
||||
/**
|
||||
* Return a type that is the non-nullable version of the given type. If `type` is already
|
||||
|
@ -385,7 +385,7 @@ export interface SymbolQuery {
|
|||
/**
|
||||
* Return the members that are in the context of a type's template reference.
|
||||
*/
|
||||
getTemplateContext(type: StaticSymbol): SymbolTable;
|
||||
getTemplateContext(type: StaticSymbol): SymbolTable|undefined;
|
||||
|
||||
/**
|
||||
* Produce a symbol table with the given symbols. Used to produce a symbol table
|
||||
|
@ -406,7 +406,7 @@ export interface SymbolQuery {
|
|||
/**
|
||||
* Return the span of the narrowest non-token node at the given location.
|
||||
*/
|
||||
getSpanAt(line: number, column: number): Span /* | undefined */;
|
||||
getSpanAt(line: number, column: number): Span|undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -519,7 +519,7 @@ export interface Completion {
|
|||
*
|
||||
* @experimental
|
||||
*/
|
||||
export type Completions = Completion[] /* | undefined */;
|
||||
export type Completions = Completion[] | undefined;
|
||||
|
||||
/**
|
||||
* A file and span.
|
||||
|
@ -532,7 +532,7 @@ export interface Location {
|
|||
/**
|
||||
* A defnition location(s).
|
||||
*/
|
||||
export type Definition = Location[] /* | undefined */;
|
||||
export type Definition = Location[] | undefined;
|
||||
|
||||
/**
|
||||
* The kind of diagnostic message.
|
||||
|
@ -597,7 +597,7 @@ export interface PipeInfo {
|
|||
*
|
||||
* @experimental
|
||||
*/
|
||||
export type Pipes = PipeInfo[] /* | undefined */;
|
||||
export type Pipes = PipeInfo[] | undefined;
|
||||
|
||||
/**
|
||||
* Describes a symbol to type binding used to build a symbol table.
|
||||
|
@ -699,30 +699,30 @@ export interface LanguageService {
|
|||
/**
|
||||
* Returns a list of all the external templates referenced by the project.
|
||||
*/
|
||||
getTemplateReferences(): string[] /* | undefined */;
|
||||
getTemplateReferences(): string[]|undefined;
|
||||
|
||||
/**
|
||||
* Returns a list of all error for all templates in the given file.
|
||||
*/
|
||||
getDiagnostics(fileName: string): Diagnostics /* | undefined */;
|
||||
getDiagnostics(fileName: string): Diagnostics|undefined;
|
||||
|
||||
/**
|
||||
* Return the completions at the given position.
|
||||
*/
|
||||
getCompletionsAt(fileName: string, position: number): Completions /* | undefined */;
|
||||
getCompletionsAt(fileName: string, position: number): Completions|undefined;
|
||||
|
||||
/**
|
||||
* Return the definition location for the symbol at position.
|
||||
*/
|
||||
getDefinitionAt(fileName: string, position: number): Definition /* | undefined */;
|
||||
getDefinitionAt(fileName: string, position: number): Definition|undefined;
|
||||
|
||||
/**
|
||||
* Return the hover information for the symbol at position.
|
||||
*/
|
||||
getHoverAt(fileName: string, position: number): Hover /* | undefined */;
|
||||
getHoverAt(fileName: string, position: number): Hover|undefined;
|
||||
|
||||
/**
|
||||
* Return the pipes that are available at the given position.
|
||||
*/
|
||||
getPipesAt(fileName: string, position: number): Pipes /* | undefined */;
|
||||
getPipesAt(fileName: string, position: number): Pipes|undefined;
|
||||
}
|
||||
|
|
|
@ -128,14 +128,14 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
return this.templateReferences;
|
||||
}
|
||||
|
||||
getTemplateAt(fileName: string, position: number): TemplateSource|undefined {
|
||||
getTemplateAt(fileName: string, position: number): TemplateSource {
|
||||
let sourceFile = this.getSourceFile(fileName);
|
||||
if (sourceFile) {
|
||||
this.context = sourceFile.fileName;
|
||||
let node = this.findNode(sourceFile, position);
|
||||
if (node) {
|
||||
return this.getSourceFromNode(
|
||||
fileName, this.host.getScriptVersion(sourceFile.fileName), node);
|
||||
fileName, this.host.getScriptVersion(sourceFile.fileName), node) !;
|
||||
}
|
||||
} else {
|
||||
this.ensureTemplateMap();
|
||||
|
@ -143,9 +143,10 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
const componentType = this.fileToComponent.get(fileName);
|
||||
if (componentType) {
|
||||
return this.getSourceFromType(
|
||||
fileName, this.host.getScriptVersion(fileName), componentType);
|
||||
fileName, this.host.getScriptVersion(fileName), componentType) !;
|
||||
}
|
||||
}
|
||||
return null !;
|
||||
}
|
||||
|
||||
getAnalyzedModules(): NgAnalyzedModules {
|
||||
|
@ -222,10 +223,10 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
updateAnalyzedModules() {
|
||||
this.validate();
|
||||
if (this.modulesOutOfDate) {
|
||||
this.analyzedModules = null;
|
||||
this._reflector = null;
|
||||
this.templateReferences = null;
|
||||
this.fileToComponent = null;
|
||||
this.analyzedModules = null !;
|
||||
this._reflector = null !;
|
||||
this.templateReferences = null !;
|
||||
this.fileToComponent = null !;
|
||||
this.ensureAnalyzedModules();
|
||||
this.modulesOutOfDate = false;
|
||||
}
|
||||
|
@ -270,10 +271,10 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
}
|
||||
|
||||
private clearCaches() {
|
||||
this._checker = null;
|
||||
this._checker = null !;
|
||||
this._typeCache = [];
|
||||
this._resolver = null;
|
||||
this.collectedErrors = null;
|
||||
this._resolver = null !;
|
||||
this.collectedErrors = null !;
|
||||
this.modulesOutOfDate = true;
|
||||
}
|
||||
|
||||
|
@ -286,7 +287,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
for (const module of ngModuleSummary.ngModules) {
|
||||
for (const directive of module.declaredDirectives) {
|
||||
const {metadata, annotation} =
|
||||
this.resolver.getNonNormalizedDirectiveMetadata(directive.reference);
|
||||
this.resolver.getNonNormalizedDirectiveMetadata(directive.reference) !;
|
||||
if (metadata.isComponent && metadata.template && metadata.template.templateUrl) {
|
||||
const templateName = urlResolver.resolve(
|
||||
componentModuleUrl(this.reflector, directive.reference, annotation),
|
||||
|
@ -343,7 +344,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
if (declaration && declaration.name) {
|
||||
const sourceFile = this.getSourceFile(fileName);
|
||||
return this.getSourceFromDeclaration(
|
||||
fileName, version, this.stringOf(node), shrink(spanOf(node)),
|
||||
fileName, version, this.stringOf(node) !, shrink(spanOf(node)),
|
||||
this.reflector.getStaticSymbol(sourceFile.fileName, declaration.name.text),
|
||||
declaration, node, sourceFile);
|
||||
}
|
||||
|
@ -357,7 +358,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
let result: TemplateSource|undefined = undefined;
|
||||
const declaration = this.getTemplateClassFromStaticSymbol(type);
|
||||
if (declaration) {
|
||||
const snapshot = this.host.getScriptSnapshot(fileName);
|
||||
const snapshot = this.host.getScriptSnapshot(fileName) !;
|
||||
const source = snapshot.getText(0, snapshot.getLength());
|
||||
result = this.getSourceFromDeclaration(
|
||||
fileName, version, source, {start: 0, end: source.length}, type, declaration, declaration,
|
||||
|
@ -410,14 +411,14 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
if (!result) {
|
||||
this._summaryResolver = new AotSummaryResolver(
|
||||
{
|
||||
loadSummary(filePath: string) { return null; },
|
||||
isSourceFile(sourceFilePath: string) { return true; },
|
||||
getOutputFileName(sourceFilePath: string) { return null; }
|
||||
loadSummary(filePath: string) { return null !; },
|
||||
isSourceFile(sourceFilePath: string) { return true !; },
|
||||
getOutputFileName(sourceFilePath: string) { return null !; }
|
||||
},
|
||||
this._staticSymbolCache);
|
||||
result = this._staticSymbolResolver = new StaticSymbolResolver(
|
||||
this.reflectorHost, this._staticSymbolCache, this._summaryResolver,
|
||||
(e, filePath) => this.collectError(e, filePath));
|
||||
this.reflectorHost as any, this._staticSymbolCache, this._summaryResolver,
|
||||
(e, filePath) => this.collectError(e, filePath !));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -427,7 +428,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
if (!result) {
|
||||
const ssr = this.staticSymbolResolver;
|
||||
result = this._reflector = new StaticReflector(
|
||||
this._summaryResolver, ssr, [], [], (e, filePath) => this.collectError(e, filePath));
|
||||
this._summaryResolver, ssr, [], [], (e, filePath) => this.collectError(e, filePath !));
|
||||
StaticAndDynamicReflectionCapabilities.install(result);
|
||||
}
|
||||
return result;
|
||||
|
@ -439,7 +440,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
const declarationNode = ts.forEachChild(source, child => {
|
||||
if (child.kind === ts.SyntaxKind.ClassDeclaration) {
|
||||
const classDeclaration = child as ts.ClassDeclaration;
|
||||
if (classDeclaration.name.text === type.name) {
|
||||
if (classDeclaration.name !.text === type.name) {
|
||||
return classDeclaration;
|
||||
}
|
||||
}
|
||||
|
@ -450,14 +451,15 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
private static missingTemplate = <[ts.ClassDeclaration, ts.Expression]>[];
|
||||
private static missingTemplate: [ts.ClassDeclaration | undefined, ts.Expression|undefined] =
|
||||
[undefined, undefined];
|
||||
|
||||
/**
|
||||
* Given a template string node, see if it is an Angular template string, and if so return the
|
||||
* containing class.
|
||||
*/
|
||||
private getTemplateClassDeclFromNode(currentToken: ts.Node):
|
||||
[ts.ClassDeclaration, ts.Expression] {
|
||||
[ts.ClassDeclaration | undefined, ts.Expression|undefined] {
|
||||
// Verify we are in a 'template' property assignment, in an object literal, which is an call
|
||||
// arg, in a decorator
|
||||
let parentNode = currentToken.parent; // PropertyAssignment
|
||||
|
@ -519,7 +521,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
|
|||
try {
|
||||
if (this.resolver.isDirective(staticSymbol as any)) {
|
||||
const {metadata} =
|
||||
this.resolver.getNonNormalizedDirectiveMetadata(staticSymbol as any);
|
||||
this.resolver.getNonNormalizedDirectiveMetadata(staticSymbol as any) !;
|
||||
const declarationSpan = spanOf(target);
|
||||
return {
|
||||
type: staticSymbol,
|
||||
|
@ -609,7 +611,7 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
private program: ts.Program, private checker: ts.TypeChecker, private source: ts.SourceFile,
|
||||
private fetchPipes: () => SymbolTable) {}
|
||||
|
||||
getTypeKind(symbol: Symbol): BuiltinType { return typeKindOf(this.getTsTypeOf(symbol)); }
|
||||
getTypeKind(symbol: Symbol): BuiltinType { return typeKindOf(this.getTsTypeOf(symbol) !); }
|
||||
|
||||
getBuiltinType(kind: BuiltinType): Symbol {
|
||||
// TODO: Replace with typeChecker API when available.
|
||||
|
@ -637,7 +639,7 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
return this.getBuiltinType(BuiltinType.Any);
|
||||
}
|
||||
|
||||
getElementType(type: Symbol): Symbol {
|
||||
getElementType(type: Symbol): Symbol|undefined {
|
||||
if (type instanceof TypeWrapper) {
|
||||
const elementType = getTypeParameterOf(type.tsType, 'Array');
|
||||
if (elementType) {
|
||||
|
@ -659,7 +661,7 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
return result;
|
||||
}
|
||||
|
||||
getTemplateContext(type: StaticSymbol): SymbolTable {
|
||||
getTemplateContext(type: StaticSymbol): SymbolTable|undefined {
|
||||
const context: TypeContext = {node: this.source, program: this.program, checker: this.checker};
|
||||
const typeSymbol = findClassSymbolInContext(type, context);
|
||||
if (typeSymbol) {
|
||||
|
@ -670,7 +672,7 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
|
||||
getTypeSymbol(type: StaticSymbol): Symbol {
|
||||
const context: TypeContext = {node: this.source, program: this.program, checker: this.checker};
|
||||
const typeSymbol = findClassSymbolInContext(type, context);
|
||||
const typeSymbol = findClassSymbolInContext(type, context) !;
|
||||
return new SymbolWrapper(typeSymbol, context);
|
||||
}
|
||||
|
||||
|
@ -688,15 +690,17 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
return result;
|
||||
}
|
||||
|
||||
getSpanAt(line: number, column: number): Span { return spanAt(this.source, line, column); }
|
||||
getSpanAt(line: number, column: number): Span|undefined {
|
||||
return spanAt(this.source, line, column);
|
||||
}
|
||||
|
||||
private getTemplateRefContextType(type: ts.Symbol): ts.Symbol {
|
||||
const constructor = type.members && type.members['__constructor'];
|
||||
private getTemplateRefContextType(type: ts.Symbol): ts.Symbol|undefined {
|
||||
const constructor = type.members && type.members !['__constructor'];
|
||||
if (constructor) {
|
||||
const constructorDeclaration = constructor.declarations[0] as ts.ConstructorTypeNode;
|
||||
const constructorDeclaration = constructor.declarations ![0] as ts.ConstructorTypeNode;
|
||||
for (const parameter of constructorDeclaration.parameters) {
|
||||
const type = this.checker.getTypeAtLocation(parameter.type);
|
||||
if (type.symbol.name == 'TemplateRef' && isReferenceType(type)) {
|
||||
const type = this.checker.getTypeAtLocation(parameter.type !);
|
||||
if (type.symbol !.name == 'TemplateRef' && isReferenceType(type)) {
|
||||
const typeReference = type as ts.TypeReference;
|
||||
if (typeReference.typeArguments.length === 1) {
|
||||
return typeReference.typeArguments[0].symbol;
|
||||
|
@ -706,7 +710,7 @@ class TypeScriptSymbolQuery implements SymbolQuery {
|
|||
}
|
||||
}
|
||||
|
||||
private getTsTypeOf(symbol: Symbol): ts.Type {
|
||||
private getTsTypeOf(symbol: Symbol): ts.Type|undefined {
|
||||
const type = this.getTypeWrapper(symbol);
|
||||
return type && type.tsType;
|
||||
}
|
||||
|
@ -838,7 +842,7 @@ class SymbolWrapper implements Symbol {
|
|||
const typeWrapper = new TypeWrapper(declaredType, this.context);
|
||||
this._members = typeWrapper.members();
|
||||
} else {
|
||||
this._members = new SymbolTableWrapper(this.symbol.members, this.context);
|
||||
this._members = new SymbolTableWrapper(this.symbol.members !, this.context);
|
||||
}
|
||||
}
|
||||
return this._members;
|
||||
|
@ -949,7 +953,7 @@ class MapSymbolTable implements SymbolTable {
|
|||
|
||||
add(symbol: Symbol) {
|
||||
if (this.map.has(symbol.name)) {
|
||||
const previous = this.map.get(symbol.name);
|
||||
const previous = this.map.get(symbol.name) !;
|
||||
this._values[this._values.indexOf(previous)] = symbol;
|
||||
}
|
||||
this.map.set(symbol.name, symbol);
|
||||
|
@ -973,18 +977,18 @@ class MapSymbolTable implements SymbolTable {
|
|||
class PipesTable implements SymbolTable {
|
||||
constructor(private pipes: Pipes, private context: TypeContext) {}
|
||||
|
||||
get size() { return this.pipes.length; }
|
||||
get size() { return this.pipes !.length; }
|
||||
|
||||
get(key: string): Symbol {
|
||||
const pipe = this.pipes.find(pipe => pipe.name == key);
|
||||
get(key: string): Symbol|undefined {
|
||||
const pipe = this.pipes !.find(pipe => pipe.name == key);
|
||||
if (pipe) {
|
||||
return new PipeSymbol(pipe, this.context);
|
||||
}
|
||||
}
|
||||
|
||||
has(key: string): boolean { return this.pipes.find(pipe => pipe.name == key) != null; }
|
||||
has(key: string): boolean { return this.pipes !.find(pipe => pipe.name == key) != null; }
|
||||
|
||||
values(): Symbol[] { return this.pipes.map(pipe => new PipeSymbol(pipe, this.context)); }
|
||||
values(): Symbol[] { return this.pipes !.map(pipe => new PipeSymbol(pipe, this.context)); }
|
||||
}
|
||||
|
||||
class PipeSymbol implements Symbol {
|
||||
|
@ -1013,11 +1017,11 @@ class PipeSymbol implements Symbol {
|
|||
signatures(): Signature[] { return signaturesOf(this.tsType, this.context); }
|
||||
|
||||
selectSignature(types: Symbol[]): Signature|undefined {
|
||||
let signature = selectSignature(this.tsType, this.context, types);
|
||||
let signature = selectSignature(this.tsType, this.context, types) !;
|
||||
if (types.length == 1) {
|
||||
const parameterType = types[0];
|
||||
if (parameterType instanceof TypeWrapper) {
|
||||
let resultType: ts.Type = undefined;
|
||||
let resultType: ts.Type|undefined = undefined;
|
||||
switch (this.name) {
|
||||
case 'async':
|
||||
switch (parameterType.name) {
|
||||
|
@ -1051,7 +1055,7 @@ class PipeSymbol implements Symbol {
|
|||
if (!type) {
|
||||
const classSymbol = this.findClassSymbol(this.pipe.symbol);
|
||||
if (classSymbol) {
|
||||
type = this._tsType = this.findTransformMethodType(classSymbol);
|
||||
type = this._tsType = this.findTransformMethodType(classSymbol) !;
|
||||
}
|
||||
if (!type) {
|
||||
type = this._tsType = getBuiltinTypeFromTs(BuiltinType.Any, this.context);
|
||||
|
@ -1060,7 +1064,7 @@ class PipeSymbol implements Symbol {
|
|||
return type;
|
||||
}
|
||||
|
||||
private findClassSymbol(type: StaticSymbol): ts.Symbol {
|
||||
private findClassSymbol(type: StaticSymbol): ts.Symbol|undefined {
|
||||
return findClassSymbolInContext(type, this.context);
|
||||
}
|
||||
|
||||
|
@ -1075,7 +1079,7 @@ class PipeSymbol implements Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
function findClassSymbolInContext(type: StaticSymbol, context: TypeContext): ts.Symbol {
|
||||
function findClassSymbolInContext(type: StaticSymbol, context: TypeContext): ts.Symbol|undefined {
|
||||
const sourceFile = context.program.getSourceFile(type.filePath);
|
||||
if (sourceFile) {
|
||||
const moduleSymbol = (sourceFile as any).module || (sourceFile as any).symbol;
|
||||
|
@ -1092,7 +1096,7 @@ class EmptyTable implements SymbolTable {
|
|||
static instance = new EmptyTable();
|
||||
}
|
||||
|
||||
function findTsConfig(fileName: string): string {
|
||||
function findTsConfig(fileName: string): string|undefined {
|
||||
let dir = path.dirname(fileName);
|
||||
while (fs.existsSync(dir)) {
|
||||
const candidate = path.join(dir, 'tsconfig.json');
|
||||
|
@ -1110,7 +1114,7 @@ function isBindingPattern(node: ts.Node): node is ts.BindingPattern {
|
|||
|
||||
function walkUpBindingElementsAndPatterns(node: ts.Node): ts.Node {
|
||||
while (node && (node.kind === ts.SyntaxKind.BindingElement || isBindingPattern(node))) {
|
||||
node = node.parent;
|
||||
node = node.parent !;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -1121,12 +1125,12 @@ function getCombinedNodeFlags(node: ts.Node): ts.NodeFlags {
|
|||
|
||||
let flags = node.flags;
|
||||
if (node.kind === ts.SyntaxKind.VariableDeclaration) {
|
||||
node = node.parent;
|
||||
node = node.parent !;
|
||||
}
|
||||
|
||||
if (node && node.kind === ts.SyntaxKind.VariableDeclarationList) {
|
||||
flags |= node.flags;
|
||||
node = node.parent;
|
||||
node = node.parent !;
|
||||
}
|
||||
|
||||
if (node && node.kind === ts.SyntaxKind.VariableStatement) {
|
||||
|
@ -1137,7 +1141,7 @@ function getCombinedNodeFlags(node: ts.Node): ts.NodeFlags {
|
|||
}
|
||||
|
||||
function isSymbolPrivate(s: ts.Symbol): boolean {
|
||||
return s.valueDeclaration && isPrivate(s.valueDeclaration);
|
||||
return !!s.valueDeclaration && isPrivate(s.valueDeclaration);
|
||||
}
|
||||
|
||||
function getBuiltinTypeFromTs(kind: BuiltinType, context: TypeContext): ts.Type {
|
||||
|
@ -1200,10 +1204,10 @@ function shrink(span: Span, offset?: number) {
|
|||
return {start: span.start + offset, end: span.end - offset};
|
||||
}
|
||||
|
||||
function spanAt(sourceFile: ts.SourceFile, line: number, column: number): Span {
|
||||
function spanAt(sourceFile: ts.SourceFile, line: number, column: number): Span|undefined {
|
||||
if (line != null && column != null) {
|
||||
const position = ts.getPositionOfLineAndCharacter(sourceFile, line, column);
|
||||
const findChild = function findChild(node: ts.Node): ts.Node {
|
||||
const findChild = function findChild(node: ts.Node): ts.Node | undefined {
|
||||
if (node.kind > ts.SyntaxKind.LastToken && node.pos <= position && node.end > position) {
|
||||
const betterNode = ts.forEachChild(node, findChild);
|
||||
return betterNode || node;
|
||||
|
@ -1230,20 +1234,20 @@ function definitionFromTsSymbol(symbol: ts.Symbol): Definition {
|
|||
}
|
||||
}
|
||||
|
||||
function parentDeclarationOf(node: ts.Node): ts.Node {
|
||||
function parentDeclarationOf(node: ts.Node): ts.Node|undefined {
|
||||
while (node) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.ClassDeclaration:
|
||||
case ts.SyntaxKind.InterfaceDeclaration:
|
||||
return node;
|
||||
case ts.SyntaxKind.SourceFile:
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
node = node.parent;
|
||||
node = node.parent !;
|
||||
}
|
||||
}
|
||||
|
||||
function getContainerOf(symbol: ts.Symbol, context: TypeContext): Symbol {
|
||||
function getContainerOf(symbol: ts.Symbol, context: TypeContext): Symbol|undefined {
|
||||
if (symbol.getFlags() & ts.SymbolFlags.ClassMember && symbol.declarations) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
const parent = parentDeclarationOf(declaration);
|
||||
|
@ -1257,7 +1261,7 @@ function getContainerOf(symbol: ts.Symbol, context: TypeContext): Symbol {
|
|||
}
|
||||
}
|
||||
|
||||
function getTypeParameterOf(type: ts.Type, name: string): ts.Type {
|
||||
function getTypeParameterOf(type: ts.Type, name: string): ts.Type|undefined {
|
||||
if (type && type.symbol && type.symbol.name == name) {
|
||||
const typeArguments: ts.Type[] = (type as any).typeArguments;
|
||||
if (typeArguments && typeArguments.length <= 1) {
|
||||
|
@ -1281,10 +1285,10 @@ function typeKindOf(type: ts.Type): BuiltinType {
|
|||
return BuiltinType.Null;
|
||||
} else if (type.flags & ts.TypeFlags.Union) {
|
||||
// If all the constituent types of a union are the same kind, it is also that kind.
|
||||
let candidate: BuiltinType;
|
||||
let candidate: BuiltinType = undefined !;
|
||||
const unionType = type as ts.UnionType;
|
||||
if (unionType.types.length > 0) {
|
||||
candidate = typeKindOf(unionType.types[0]);
|
||||
candidate = typeKindOf(unionType.types[0]) !;
|
||||
for (const subType of unionType.types) {
|
||||
if (candidate != typeKindOf(subType)) {
|
||||
return BuiltinType.Other;
|
||||
|
|
|
@ -13,7 +13,7 @@ import {Span} from './types';
|
|||
|
||||
export interface SpanHolder {
|
||||
sourceSpan: ParseSourceSpan;
|
||||
endSourceSpan?: ParseSourceSpan;
|
||||
endSourceSpan?: ParseSourceSpan|null;
|
||||
children?: SpanHolder[];
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ export function isParseSourceSpan(value: any): value is ParseSourceSpan {
|
|||
return value && !!value.start;
|
||||
}
|
||||
|
||||
export function spanOf(span?: SpanHolder | ParseSourceSpan): Span {
|
||||
export function spanOf(span?: SpanHolder | ParseSourceSpan): Span|undefined {
|
||||
if (!span) return undefined;
|
||||
if (isParseSourceSpan(span)) {
|
||||
return {start: span.start.offset, end: span.end.offset};
|
||||
|
@ -31,7 +31,7 @@ export function spanOf(span?: SpanHolder | ParseSourceSpan): Span {
|
|||
} else if (span.children && span.children.length) {
|
||||
return {
|
||||
start: span.sourceSpan.start.offset,
|
||||
end: spanOf(span.children[span.children.length - 1]).end
|
||||
end: spanOf(span.children[span.children.length - 1]) !.end
|
||||
};
|
||||
}
|
||||
return {start: span.sourceSpan.start.offset, end: span.sourceSpan.end.offset};
|
||||
|
@ -40,7 +40,7 @@ export function spanOf(span?: SpanHolder | ParseSourceSpan): Span {
|
|||
|
||||
export function inSpan(position: number, span?: Span, exclusive?: boolean): boolean {
|
||||
return span && exclusive ? position >= span.start && position < span.end :
|
||||
position >= span.start && position <= span.end;
|
||||
position >= span !.start && position <= span !.end;
|
||||
}
|
||||
|
||||
export function offsetSpan(span: Span, amount: number): Span {
|
||||
|
@ -54,7 +54,7 @@ export function isNarrower(spanA: Span, spanB: Span): boolean {
|
|||
export function hasTemplateReference(type: CompileTypeMetadata): boolean {
|
||||
if (type.diDeps) {
|
||||
for (let diDep of type.diDeps) {
|
||||
if (diDep.token.identifier && identifierName(diDep.token.identifier) == 'TemplateRef')
|
||||
if (diDep.token !.identifier && identifierName(diDep.token !.identifier !) == 'TemplateRef')
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ export function hasTemplateReference(type: CompileTypeMetadata): boolean {
|
|||
|
||||
export function getSelectors(info: TemplateInfo): SelectorInfo {
|
||||
const map = new Map<CssSelector, CompileDirectiveSummary>();
|
||||
const selectors = flatten(info.directives.map(directive => {
|
||||
const selectors = CssSelector.parse(directive.selector);
|
||||
const selectors: CssSelector[] = flatten(info.directives.map(directive => {
|
||||
const selectors: CssSelector[] = CssSelector.parse(directive.selector !);
|
||||
selectors.forEach(selector => map.set(selector, directive));
|
||||
return selectors;
|
||||
}));
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('completions', () => {
|
|||
const fileName = '/app/test.ng';
|
||||
mockHost.override(fileName, ' > {{tle<\n {{retl ><bel/beled}}di>\n la</b </d &a ');
|
||||
expect(() => ngService.getCompletionsAt(fileName, 31)).not.toThrow();
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
});
|
||||
|
||||
it('should be able to infer the type of a ngForOf', () => {
|
||||
|
@ -101,7 +101,7 @@ describe('completions', () => {
|
|||
}
|
||||
}
|
||||
try {
|
||||
const originalContent = mockHost.getFileContent(fileName);
|
||||
const originalContent = mockHost.getFileContent(fileName) !;
|
||||
|
||||
// For each character in the file, add it to the file and request a completion after it.
|
||||
for (let index = 0, len = originalContent.length; index < len; index++) {
|
||||
|
@ -133,7 +133,7 @@ describe('completions', () => {
|
|||
tryCompletionsAt(position);
|
||||
});
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
@ -169,12 +169,12 @@ export class MyComponent {
|
|||
try {
|
||||
cb(fileName, newContent);
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}
|
||||
|
||||
function contains(fileName: string, locationMarker: string, ...names: string[]) {
|
||||
let location = mockHost.getMarkerLocations(fileName)[locationMarker];
|
||||
let location = mockHost.getMarkerLocations(fileName) ![locationMarker];
|
||||
if (location == null) {
|
||||
throw new Error(`No marker ${locationMarker} found.`);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ describe('definitions', () => {
|
|||
|
||||
function localReference(code: string) {
|
||||
addCode(code, fileName => {
|
||||
const refResult = mockHost.getReferenceMarkers(fileName);
|
||||
const refResult = mockHost.getReferenceMarkers(fileName) !;
|
||||
for (const name in refResult.references) {
|
||||
const references = refResult.references[name];
|
||||
const definitions = refResult.definitions[name];
|
||||
|
@ -100,14 +100,14 @@ describe('definitions', () => {
|
|||
const definition: string = p2 ? p1 : undefined;
|
||||
let span: Span = p2 && p1.start != null ? p1 : undefined;
|
||||
if (definition && !span) {
|
||||
const referencedFileMarkers = mockHost.getReferenceMarkers(referencedFile);
|
||||
const referencedFileMarkers = mockHost.getReferenceMarkers(referencedFile) !;
|
||||
expect(referencedFileMarkers).toBeDefined(); // If this fails the test data is wrong.
|
||||
const spans = referencedFileMarkers.definitions[definition];
|
||||
expect(spans).toBeDefined(); // If this fails the test data is wrong.
|
||||
span = spans[0];
|
||||
}
|
||||
addCode(code, fileName => {
|
||||
const refResult = mockHost.getReferenceMarkers(fileName);
|
||||
const refResult = mockHost.getReferenceMarkers(fileName) !;
|
||||
let tests = 0;
|
||||
for (const name in refResult.references) {
|
||||
const references = refResult.references[name];
|
||||
|
@ -144,12 +144,12 @@ describe('definitions', () => {
|
|||
try {
|
||||
cb(fileName, newContent);
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function matchingSpan(aSpans: Span[], bSpans: Span[]): Span {
|
||||
function matchingSpan(aSpans: Span[], bSpans: Span[]): Span|undefined {
|
||||
for (const a of aSpans) {
|
||||
for (const b of bSpans) {
|
||||
if (a.start == b.start && a.end == b.end) {
|
||||
|
|
|
@ -32,9 +32,9 @@ describe('diagnostics', () => {
|
|||
function diagnostics(template: string): Diagnostics {
|
||||
try {
|
||||
mockHost.override(fileName, template);
|
||||
return ngService.getDiagnostics(fileName);
|
||||
return ngService.getDiagnostics(fileName) !;
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,10 @@ describe('diagnostics', () => {
|
|||
const code = '\n@Component({template: \'<div></div>\'}) export class MyComponent {}';
|
||||
addCode(code, (fileName, content) => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
const offset = content.lastIndexOf('@Component') + 1;
|
||||
const offset = content !.lastIndexOf('@Component') + 1;
|
||||
const len = 'Component'.length;
|
||||
includeDiagnostic(
|
||||
diagnostics, 'Component \'MyComponent\' is not included in a module', offset, len);
|
||||
diagnostics !, 'Component \'MyComponent\' is not included in a module', offset, len);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -95,7 +95,7 @@ describe('diagnostics', () => {
|
|||
const code = '\n@Component({template: \'<form></form>\'}) export class MyComponent {}';
|
||||
addCode(code, (fileName, content) => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
onlyModuleDiagnostics(diagnostics);
|
||||
onlyModuleDiagnostics(diagnostics !);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -119,7 +119,7 @@ describe('diagnostics', () => {
|
|||
addCode(code, (fileName, content) => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
includeDiagnostic(
|
||||
diagnostics, 'Function calls are not supported.', '() => \'foo\'', content);
|
||||
diagnostics !, 'Function calls are not supported.', '() => \'foo\'', content);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -134,7 +134,7 @@ describe('diagnostics', () => {
|
|||
` @Component({template: \`<div *ngIf="something === 'foo'"></div>\`}) export class MyComponent { something: 'foo' | 'bar'; }`;
|
||||
addCode(code, fileName => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
onlyModuleDiagnostics(diagnostics);
|
||||
onlyModuleDiagnostics(diagnostics !);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -144,7 +144,7 @@ describe('diagnostics', () => {
|
|||
addCode(code, (fileName, content) => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
includeDiagnostic(
|
||||
diagnostics, 'Unexpected callable expression. Expected a method call', 'onClick',
|
||||
diagnostics !, 'Unexpected callable expression. Expected a method call', 'onClick',
|
||||
content);
|
||||
});
|
||||
});
|
||||
|
@ -155,7 +155,7 @@ describe('diagnostics', () => {
|
|||
` @Component({template: \`<div *ngIf="something === undefined"></div>\`}) export class MyComponent { something = 'foo'; }})`;
|
||||
addCode(code, fileName => {
|
||||
const diagnostics = ngService.getDiagnostics(fileName);
|
||||
onlyModuleDiagnostics(diagnostics);
|
||||
onlyModuleDiagnostics(diagnostics !);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -165,7 +165,7 @@ describe('diagnostics', () => {
|
|||
` @Component({template: '<p> Using an invalid pipe {{data | dat}} </p>'}) export class MyComponent { data = 'some data'; }`;
|
||||
addCode(code, fileName => {
|
||||
const diagnostic =
|
||||
ngService.getDiagnostics(fileName).filter(d => d.message.indexOf('pipe') > 0)[0];
|
||||
ngService.getDiagnostics(fileName) !.filter(d => d.message.indexOf('pipe') > 0)[0];
|
||||
expect(diagnostic).not.toBeUndefined();
|
||||
expect(diagnostic.span.end - diagnostic.span.start).toBeLessThan(11);
|
||||
});
|
||||
|
@ -267,7 +267,7 @@ describe('diagnostics', () => {
|
|||
try {
|
||||
cb(fileName, newContent);
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ describe('hover', () => {
|
|||
function hover(code: string, hoverText: string) {
|
||||
addCode(code, fileName => {
|
||||
let tests = 0;
|
||||
const markers = mockHost.getReferenceMarkers(fileName);
|
||||
const markers = mockHost.getReferenceMarkers(fileName) !;
|
||||
const keys = Object.keys(markers.references).concat(Object.keys(markers.definitions));
|
||||
for (const referenceName of keys) {
|
||||
const references = (markers.references[referenceName] ||
|
||||
|
@ -96,7 +96,7 @@ describe('hover', () => {
|
|||
try {
|
||||
cb(fileName, newContent);
|
||||
} finally {
|
||||
mockHost.override(fileName, undefined);
|
||||
mockHost.override(fileName, undefined !);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('service without angular', () => {
|
|||
let ngHost = new TypeScriptServiceHost(mockHost, service);
|
||||
let ngService = createLanguageService(ngHost);
|
||||
const fileName = '/app/test.ng';
|
||||
let position = mockHost.getMarkerLocations(fileName)['h1-content'];
|
||||
let position = mockHost.getMarkerLocations(fileName) !['h1-content'];
|
||||
|
||||
it('should not crash a get template references',
|
||||
() => expect(() => ngService.getTemplateReferences()));
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('references', () => {
|
|||
let service: ts.LanguageService;
|
||||
let program: ts.Program;
|
||||
let ngHost: TypeScriptServiceHost;
|
||||
let ngService: LanguageService = createLanguageService(ngHost);
|
||||
let ngService: LanguageService = createLanguageService(undefined !);
|
||||
|
||||
beforeEach(() => {
|
||||
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
|
||||
|
|
|
@ -63,7 +63,7 @@ missingCache.set(
|
|||
missingCache.set('/node_modules/@angular/forms/src/directives/form_interface.metadata.json', true);
|
||||
|
||||
export class MockTypescriptHost implements ts.LanguageServiceHost {
|
||||
private angularPath: string;
|
||||
private angularPath: string|undefined;
|
||||
private nodeModulesPath: string;
|
||||
private scriptVersion = new Map<string, number>();
|
||||
private overrides = new Map<string, string>();
|
||||
|
@ -120,7 +120,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
|
|||
return (this.scriptVersion.get(fileName) || 0).toString();
|
||||
}
|
||||
|
||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot|undefined {
|
||||
const content = this.getFileContent(fileName);
|
||||
if (content) return ts.ScriptSnapshot.fromString(content);
|
||||
return undefined;
|
||||
|
@ -145,19 +145,19 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
|
|||
}
|
||||
}
|
||||
|
||||
getReferenceMarkers(fileName: string): ReferenceResult {
|
||||
getReferenceMarkers(fileName: string): ReferenceResult|undefined {
|
||||
let content = this.getRawFileContent(fileName);
|
||||
if (content) {
|
||||
return getReferenceMarkers(content);
|
||||
}
|
||||
}
|
||||
|
||||
getFileContent(fileName: string): string {
|
||||
getFileContent(fileName: string): string|undefined {
|
||||
const content = this.getRawFileContent(fileName);
|
||||
if (content) return removeReferenceMarkers(removeLocationMarkers(content));
|
||||
}
|
||||
|
||||
private getRawFileContent(fileName: string): string {
|
||||
private getRawFileContent(fileName: string): string|undefined {
|
||||
if (this.overrides.has(fileName)) {
|
||||
return this.overrides.get(fileName);
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ function find(fileName: string, data: MockData): MockData|undefined {
|
|||
if (typeof current === 'string')
|
||||
return undefined;
|
||||
else
|
||||
current = (<MockDirectory>current)[name];
|
||||
current = (<MockDirectory>current)[name] !;
|
||||
if (!current) return undefined;
|
||||
}
|
||||
return current;
|
||||
|
@ -241,7 +241,7 @@ function open(fileName: string, data: MockData): string|undefined {
|
|||
|
||||
function directoryExists(dirname: string, data: MockData): boolean {
|
||||
let result = find(dirname, data);
|
||||
return result && typeof result !== 'string';
|
||||
return !!result && typeof result !== 'string';
|
||||
}
|
||||
|
||||
const locationMarker = /\~\{(\w+(-\w+)*)\}/g;
|
||||
|
|
|
@ -195,7 +195,7 @@ describe('plugin', () => {
|
|||
});
|
||||
|
||||
function getMarkerLocation(fileName: string, locationMarker: string): number {
|
||||
const location = mockHost.getMarkerLocations(fileName)[locationMarker];
|
||||
const location = mockHost.getMarkerLocations(fileName) ![locationMarker];
|
||||
if (location == null) {
|
||||
throw new Error(`No marker ${locationMarker} found.`);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"stripInternal": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"strictNullChecks": true,
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "../../dist/packages/language-service",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"emitDecoratorMetadata": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"strictNullChecks": false,
|
||||
"outDir": "../dist/all/@angular",
|
||||
"noImplicitAny": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
|
Loading…
Reference in New Issue