diff --git a/packages/compiler/src/i18n/extractor_merger.ts b/packages/compiler/src/i18n/extractor_merger.ts index b1640440e1..56d8fe6b61 100644 --- a/packages/compiler/src/i18n/extractor_merger.ts +++ b/packages/compiler/src/i18n/extractor_merger.ts @@ -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); diff --git a/packages/compiler/src/ml_parser/ast.ts b/packages/compiler/src/ml_parser/ast.ts index f84dedb0c3..03ebb292da 100644 --- a/packages/compiler/src/ml_parser/ast.ts +++ b/packages/compiler/src/ml_parser/ast.ts @@ -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); } } diff --git a/packages/compiler/src/template_parser/template_ast.ts b/packages/compiler/src/template_parser/template_ast.ts index 7a66a39eab..63b526e048 100644 --- a/packages/compiler/src/template_parser/template_ast.ts +++ b/packages/compiler/src/template_parser/template_ast.ts @@ -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); diff --git a/packages/compiler/src/template_parser/template_parser.ts b/packages/compiler/src/template_parser/template_parser.ts index 6792e6b5fd..22736d68b6 100644 --- a/packages/compiler/src/template_parser/template_parser.ts +++ b/packages/compiler/src/template_parser/template_parser.ts @@ -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); } diff --git a/packages/language-service/src/ast_path.ts b/packages/language-service/src/ast_path.ts index bc570988bd..a1003945f9 100644 --- a/packages/language-service/src/ast_path.ts +++ b/packages/language-service/src/ast_path.ts @@ -25,5 +25,5 @@ export class AstPath { push(node: T) { this.path.push(node); } - pop(): T { return this.path.pop(); } + pop(): T { return this.path.pop() !; } } diff --git a/packages/language-service/src/completions.ts b/packages/language-service/src/completions.ts index 53591902b1..031268d0c3 100644 --- a/packages/language-service/src/completions.ts +++ b/packages/language-service/src/completions.ts @@ -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(selectorAndAttr => { - const directive = selectorMap.get(selectorAndAttr.selector); + const directive = selectorMap.get(selectorAndAttr.selector) !; const result = selectorAndAttr.attrs.map( 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(name => ({kind: 'component', name: name, sort: name})); + directiveElements.map(name => ({kind: 'component', name: name !, sort: name !})); let htmlElements = htmlNames.map(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 `= 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; } } diff --git a/packages/language-service/src/diagnostics.ts b/packages/language-service/src/diagnostics.ts index 2b672f8d71..fd84836862 100644 --- a/packages/language-service/src/diagnostics.ts +++ b/packages/language-service/src/diagnostics.ts @@ -29,7 +29,7 @@ export function getTemplateDiagnostics( results.push(...ast.parseErrors.map( 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; diff --git a/packages/language-service/src/expressions.ts b/packages/language-service/src/expressions.ts index 2f3a483834..3d6b567a3f 100644 --- a/packages/language-service/src/expressions.ts +++ b/packages/language-service/src/expressions.ts @@ -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 [{ diff --git a/packages/language-service/src/hover.ts b/packages/language-service/src/hover.ts index 9f62881bcc..bc28e2f349 100644 --- a/packages/language-service/src/hover.ts +++ b/packages/language-service/src/hover.ts @@ -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}; diff --git a/packages/language-service/src/html_path.ts b/packages/language-service/src/html_path.ts index 152ad95468..7cfd5ebf8e 100644 --- a/packages/language-service/src/html_path.ts +++ b/packages/language-service/src/html_path.ts @@ -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 { diff --git a/packages/language-service/src/language_service.ts b/packages/language-service/src/language_service.ts index 1219f2a818..36b60bb334 100644 --- a/packages/language-service/src/language_service.ts +++ b/packages/language-service/src/language_service.ts @@ -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; diff --git a/packages/language-service/src/locate_symbol.ts b/packages/language-service/src/locate_symbol.ts index 6e86f82e51..5f55f2c48b 100644 --- a/packages/language-service/src/locate_symbol.ts +++ b/packages/language-service/src/locate_symbol.ts @@ -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) { diff --git a/packages/language-service/src/reflector_host.ts b/packages/language-service/src/reflector_host.ts index a8a8a787c6..086cb48b69 100644 --- a/packages/language-service/src/reflector_host.ts +++ b/packages/language-service/src/reflector_host.ts @@ -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}); } diff --git a/packages/language-service/src/template_path.ts b/packages/language-service/src/template_path.ts index e974e39563..07fca912ad 100644 --- a/packages/language-service/src/template_path.ts +++ b/packages/language-service/src/template_path.ts @@ -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 { diff --git a/packages/language-service/src/ts_plugin.ts b/packages/language-service/src/ts_plugin.ts index b4e6721f85..ae689bc5f4 100644 --- a/packages/language-service/src/ts_plugin.ts +++ b/packages/language-service/src/ts_plugin.ts @@ -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, diff --git a/packages/language-service/src/types.ts b/packages/language-service/src/types.ts index b187f03a7d..fe29b27247 100644 --- a/packages/language-service/src/types.ts +++ b/packages/language-service/src/types.ts @@ -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; } diff --git a/packages/language-service/src/typescript_host.ts b/packages/language-service/src/typescript_host.ts index 4eb60a6eb6..84344ce630 100644 --- a/packages/language-service/src/typescript_host.ts +++ b/packages/language-service/src/typescript_host.ts @@ -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; diff --git a/packages/language-service/src/utils.ts b/packages/language-service/src/utils.ts index f971a33049..3287be5440 100644 --- a/packages/language-service/src/utils.ts +++ b/packages/language-service/src/utils.ts @@ -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(); - 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; })); diff --git a/packages/language-service/test/completions_spec.ts b/packages/language-service/test/completions_spec.ts index db4dc1e2f8..2b1b8f410b 100644 --- a/packages/language-service/test/completions_spec.ts +++ b/packages/language-service/test/completions_spec.ts @@ -48,7 +48,7 @@ describe('completions', () => { const fileName = '/app/test.ng'; mockHost.override(fileName, ' > {{tle<\n {{retl >\n la 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.`); } diff --git a/packages/language-service/test/definitions_spec.ts b/packages/language-service/test/definitions_spec.ts index 99080731f4..8c0aced320 100644 --- a/packages/language-service/test/definitions_spec.ts +++ b/packages/language-service/test/definitions_spec.ts @@ -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) { diff --git a/packages/language-service/test/diagnostics_spec.ts b/packages/language-service/test/diagnostics_spec.ts index db4d359d83..eb9131f9ef 100644 --- a/packages/language-service/test/diagnostics_spec.ts +++ b/packages/language-service/test/diagnostics_spec.ts @@ -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: \'
\'}) 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: \'
\'}) 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: \`
\`}) 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: \`
\`}) 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: '

Using an invalid pipe {{data | dat}}

'}) 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 !); } } diff --git a/packages/language-service/test/hover_spec.ts b/packages/language-service/test/hover_spec.ts index 5cf7a8a926..3cada95ae2 100644 --- a/packages/language-service/test/hover_spec.ts +++ b/packages/language-service/test/hover_spec.ts @@ -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 !); } } diff --git a/packages/language-service/test/language_service_spec.ts b/packages/language-service/test/language_service_spec.ts index aba0d16b99..0aa5537185 100644 --- a/packages/language-service/test/language_service_spec.ts +++ b/packages/language-service/test/language_service_spec.ts @@ -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())); diff --git a/packages/language-service/test/template_references_spec.ts b/packages/language-service/test/template_references_spec.ts index 227b49d9fe..78040ecb4d 100644 --- a/packages/language-service/test/template_references_spec.ts +++ b/packages/language-service/test/template_references_spec.ts @@ -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); diff --git a/packages/language-service/test/test_utils.ts b/packages/language-service/test/test_utils.ts index 3f7a1d7193..380c652ad9 100644 --- a/packages/language-service/test/test_utils.ts +++ b/packages/language-service/test/test_utils.ts @@ -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(); private overrides = new Map(); @@ -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 = (current)[name]; + current = (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; diff --git a/packages/language-service/test/ts_plugin_spec.ts b/packages/language-service/test/ts_plugin_spec.ts index f9ab921f86..bbed4adcc7 100644 --- a/packages/language-service/test/ts_plugin_spec.ts +++ b/packages/language-service/test/ts_plugin_spec.ts @@ -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.`); } diff --git a/packages/language-service/tsconfig-build.json b/packages/language-service/tsconfig-build.json index c30b273fc1..bab561736e 100644 --- a/packages/language-service/tsconfig-build.json +++ b/packages/language-service/tsconfig-build.json @@ -5,6 +5,7 @@ "stripInternal": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, + "strictNullChecks": true, "module": "es2015", "moduleResolution": "node", "outDir": "../../dist/packages/language-service", diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 4675584dd1..6020735526 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -6,6 +6,7 @@ "emitDecoratorMetadata": true, "module": "commonjs", "moduleResolution": "node", + "strictNullChecks": false, "outDir": "../dist/all/@angular", "noImplicitAny": true, "noFallthroughCasesInSwitch": true,