From b31b45f584282175281a04c4e465115e4dde6c6a Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 26 Oct 2015 15:42:25 -0700 Subject: [PATCH 01/75] JavaScript class inference from prototype property assignment --- src/compiler/binder.ts | 32 ++++++++++++++ src/compiler/checker.ts | 43 +++++++++++++------ src/compiler/types.ts | 2 + src/compiler/utilities.ts | 29 +++++++++++++ src/services/services.ts | 1 + tests/cases/fourslash/javaScriptPrototype1.ts | 36 ++++++++++++++++ 6 files changed, 129 insertions(+), 14 deletions(-) create mode 100644 tests/cases/fourslash/javaScriptPrototype1.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index d5ab7dd11ca..bfef27a9102 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -622,6 +622,7 @@ namespace ts { function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) { let symbol = createSymbol(symbolFlags, name); addDeclarationToSymbol(symbol, node, symbolFlags); + return symbol; } function bindBlockScopedDeclaration(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { @@ -867,6 +868,9 @@ namespace ts { else if (isModuleExportsAssignment(node)) { bindModuleExportsAssignment(node); } + else if (isPrototypePropertyAssignment(node)) { + bindPrototypePropertyAssignment(node); + } } return checkStrictModeBinaryExpression(node); case SyntaxKind.CatchClause: @@ -1034,6 +1038,34 @@ namespace ts { bindExportAssignment(node); } + function bindPrototypePropertyAssignment(node: BinaryExpression) { + // We saw a node of the form 'x.prototype.y = z'. + // This does two things: turns 'x' into a constructor function, and + // adds a member 'y' to the result of that constructor function + // Get 'x', the class + let classId = ((node.left).expression).expression; + + // Look up the function in the local scope, since prototype assignments should immediately + // follow the function declaration + let funcSymbol = container.locals[classId.text]; + if (!funcSymbol) { + return; + } + + // The function is now a constructor rather than a normal function + if (!funcSymbol.inferredConstructor) { + funcSymbol.flags = (funcSymbol.flags | SymbolFlags.Class) & ~SymbolFlags.Function; + funcSymbol.members = funcSymbol.members || {}; + funcSymbol.members["__constructor"] = funcSymbol; + funcSymbol.inferredConstructor = true; + } + + // Get 'y', the property name, and add it to the type of the class + let propertyName = (node.left).name; + let prototypeSymbol = declareSymbol(funcSymbol.members, funcSymbol, (node.left).expression, SymbolFlags.HasMembers, SymbolFlags.None); + declareSymbol(prototypeSymbol.members, prototypeSymbol, node.left, SymbolFlags.Method | SymbolFlags.Property, SymbolFlags.None); + } + function bindCallExpression(node: CallExpression) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip // this check if we've already seen the module indicator diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac5056bf769..24da884a330 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -122,8 +122,8 @@ namespace ts { let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - let anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, false, false); - let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, false, false); + let anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, undefined, 0, false, false); + let unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, undefined, 0, false, false); let globals: SymbolTable = {}; @@ -3247,12 +3247,13 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], kind: SignatureKind, resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature { let sig = new Signature(checker); sig.declaration = declaration; sig.typeParameters = typeParameters; sig.parameters = parameters; + sig.kind = kind; sig.resolvedReturnType = resolvedReturnType; sig.typePredicate = typePredicate; sig.minArgumentCount = minArgumentCount; @@ -3262,13 +3263,13 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.typePredicate, + return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.kind, sig.resolvedReturnType, sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { if (!getBaseTypes(classType).length) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, false, false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, SignatureKind.Construct, classType, undefined, 0, false, false)]; } let baseConstructorType = getBaseConstructorTypeOfClass(classType); let baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); @@ -3788,7 +3789,26 @@ namespace ts { } } - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, typePredicate, + let kind: SignatureKind; + switch (declaration.kind) { + case SyntaxKind.Constructor: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructorType: + kind = SignatureKind.Construct; + break; + default: + if (declaration.symbol.inferredConstructor) { + kind = SignatureKind.Construct; + let proto = declaration.symbol.members["prototype"]; + returnType = createAnonymousType(createSymbol(SymbolFlags.None, "__jsClass"), proto.members, emptyArray, emptyArray, undefined, undefined); + } + else { + kind = SignatureKind.Call; + } + break; + } + + links.resolvedSignature = createSignature(declaration, typeParameters, parameters, kind, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; @@ -3905,7 +3925,7 @@ namespace ts { // object type literal or interface (using the new keyword). Each way of declaring a constructor // will result in a different declaration kind. if (!signature.isolatedSignatureType) { - let isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature; + let isConstructor = signature.kind === SignatureKind.Construct; let type = createObjectType(TypeFlags.Anonymous | TypeFlags.FromSignature); type.members = emptySymbols; type.properties = emptyArray; @@ -4611,6 +4631,7 @@ namespace ts { } let result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), + signature.kind, instantiateType(signature.resolvedReturnType, mapper), freshTypePredicate, signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals); @@ -9359,13 +9380,7 @@ namespace ts { return voidType; } if (node.kind === SyntaxKind.NewExpression) { - let declaration = signature.declaration; - - if (declaration && - declaration.kind !== SyntaxKind.Constructor && - declaration.kind !== SyntaxKind.ConstructSignature && - declaration.kind !== SyntaxKind.ConstructorType) { - + if (signature.kind === SignatureKind.Call) { // When resolved signature is a call signature (and not a construct signature) the result type is any if (compilerOptions.noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5e8de9a3fb4..5232209e7d1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1714,6 +1714,7 @@ namespace ts { /* @internal */ parent?: Symbol; // Parent symbol /* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol /* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums + /* @internal */ inferredConstructor?: boolean; // A function promoted to constructor as the result of a prototype property assignment } /* @internal */ @@ -1958,6 +1959,7 @@ namespace ts { declaration: SignatureDeclaration; // Originating declaration typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters + kind: SignatureKind; // Call or Construct typePredicate?: TypePredicate; // Type predicate /* @internal */ resolvedReturnType: Type; // Resolved return type diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9eff4370ec2..05184e29f58 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1086,6 +1086,35 @@ namespace ts { (((expression).left).name.text === "exports"); } + /** + * Returns true if this expression is an assignment to the given named property + */ + function isAssignmentToProperty(expression: Node, name?: string): expression is BinaryExpression { + return (expression.kind === SyntaxKind.BinaryExpression) && + ((expression).operatorToken.kind === SyntaxKind.EqualsToken) && + isNamedPropertyAccess((expression).left, name); + } + + /** + * Returns true if this expression is a PropertyAccessExpression where the property name is the provided name + */ + function isNamedPropertyAccess(expression: Node, name?: string): expression is PropertyAccessExpression { + return expression.kind === SyntaxKind.PropertyAccessExpression && + (!name || (expression).name.text === name); + } + + /** + * Returns true if the node is an assignment in the form 'id1.prototype.id2 = expr' where id1 and id2 + * are any identifier. + * This function does not test if the node is in a JavaScript file or not. + */ + export function isPrototypePropertyAssignment(expression: Node): expression is BinaryExpression { + return isAssignmentToProperty(expression) && + isNamedPropertyAccess(expression.left) && + isNamedPropertyAccess((expression.left).expression, "prototype") && + ((expression.left).expression).expression.kind === SyntaxKind.Identifier; + } + export function getExternalModuleName(node: Node): Expression { if (node.kind === SyntaxKind.ImportDeclaration) { return (node).moduleSpecifier; diff --git a/src/services/services.ts b/src/services/services.ts index 30d993cb6b6..2c2bbb8e73e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -735,6 +735,7 @@ namespace ts { declaration: SignatureDeclaration; typeParameters: TypeParameter[]; parameters: Symbol[]; + kind: SignatureKind; resolvedReturnType: Type; minArgumentCount: number; hasRestParameter: boolean; diff --git a/tests/cases/fourslash/javaScriptPrototype1.ts b/tests/cases/fourslash/javaScriptPrototype1.ts new file mode 100644 index 00000000000..0dec8d721d6 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype1.ts @@ -0,0 +1,36 @@ +/// + +// Assignments to the 'prototype' property of a function create a class + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// } +//// myCtor.prototype.foo = function() { return 32 }; +//// myCtor.prototype.bar = function() { return '' }; +//// +//// var m = new myCtor(10); +//// m/*1*/ +//// var x = m.foo(); +//// x/*2*/ +//// var y = m.bar(); +//// y/*3*/ + +goTo.marker('1'); +edit.insert('.'); +verify.memberListContains('foo', undefined, undefined, 'method'); +edit.insert('foo'); + +edit.backspace(); +edit.backspace(); + +goTo.marker('2'); +edit.insert('.'); +verify.memberListContains('toFixed', undefined, undefined, 'method'); +verify.not.memberListContains('substr', undefined, undefined, 'method'); +edit.backspace(); + +goTo.marker('3'); +edit.insert('.'); +verify.memberListContains('substr', undefined, undefined, 'method'); +verify.not.memberListContains('toFixed', undefined, undefined, 'method'); From bc3d95c0a41c833802d0939ecda081a167565b02 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 27 Oct 2015 17:17:31 -0700 Subject: [PATCH 02/75] JS class members as methods --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index bfef27a9102..85882c495b6 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1063,7 +1063,7 @@ namespace ts { // Get 'y', the property name, and add it to the type of the class let propertyName = (node.left).name; let prototypeSymbol = declareSymbol(funcSymbol.members, funcSymbol, (node.left).expression, SymbolFlags.HasMembers, SymbolFlags.None); - declareSymbol(prototypeSymbol.members, prototypeSymbol, node.left, SymbolFlags.Method | SymbolFlags.Property, SymbolFlags.None); + declareSymbol(prototypeSymbol.members, prototypeSymbol, node.left, SymbolFlags.Method, SymbolFlags.None); } function bindCallExpression(node: CallExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 24da884a330..f0bdd48afa7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3843,6 +3843,11 @@ namespace ts { } } result.push(getSignatureFromDeclaration(node)); + break; + + case SyntaxKind.PropertyAccessExpression: + // Class inference from ClassName.prototype.methodName = expr + return getSignaturesOfType(checkExpressionCached((node.parent).right), SignatureKind.Call); } } return result; From 3b7213116d324585dc73548dc2289f8513b1884c Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 30 Oct 2015 12:34:56 -0700 Subject: [PATCH 03/75] Inference from JavaScript `prototype` property assignments --- src/compiler/binder.ts | 58 ++++++++++++++----- src/compiler/checker.ts | 31 +++++++--- src/compiler/types.ts | 13 +++++ src/compiler/utilities.ts | 36 ++++++++++++ tests/cases/fourslash/javaScriptPrototype1.ts | 26 ++++++--- tests/cases/fourslash/javaScriptPrototype2.ts | 36 ++++++++++++ tests/cases/fourslash/javaScriptPrototype3.ts | 40 +++++++++++++ tests/cases/fourslash/javaScriptPrototype4.ts | 36 ++++++++++++ 8 files changed, 247 insertions(+), 29 deletions(-) create mode 100644 tests/cases/fourslash/javaScriptPrototype2.ts create mode 100644 tests/cases/fourslash/javaScriptPrototype3.ts create mode 100644 tests/cases/fourslash/javaScriptPrototype4.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 85882c495b6..9bd51f0c763 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -167,8 +167,21 @@ namespace ts { case SyntaxKind.ExportAssignment: return (node).isExportEquals ? "export=" : "default"; case SyntaxKind.BinaryExpression: - // Binary expression case is for JS module 'module.exports = expr' - return "export="; + switch (getSpecialPropertyAssignmentKind(node)) { + case SpecialPropertyAssignmentKind.ModuleExports: + // module.exports = ... + return "export="; + case SpecialPropertyAssignmentKind.ExportsProperty: + case SpecialPropertyAssignmentKind.ThisProperty: + // exports.x = ... or this.y = ... + return ((node as BinaryExpression).left as PropertyAccessExpression).name.text; + case SpecialPropertyAssignmentKind.PrototypeProperty: + // className.prototype.methodName = ... + return (((node as BinaryExpression).left as PropertyAccessExpression).expression as PropertyAccessExpression).name.text; + } + Debug.fail("Unknown binary declaration kind"); + break; + case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: return node.flags & NodeFlags.Default ? "default" : undefined; @@ -862,14 +875,20 @@ namespace ts { return checkStrictModeIdentifier(node); case SyntaxKind.BinaryExpression: if (isJavaScriptFile) { - if (isExportsPropertyAssignment(node)) { - bindExportsPropertyAssignment(node); - } - else if (isModuleExportsAssignment(node)) { - bindModuleExportsAssignment(node); - } - else if (isPrototypePropertyAssignment(node)) { - bindPrototypePropertyAssignment(node); + let specialKind = getSpecialPropertyAssignmentKind(node); + switch (specialKind) { + case SpecialPropertyAssignmentKind.ExportsProperty: + bindExportsPropertyAssignment(node); + break; + case SpecialPropertyAssignmentKind.ModuleExports: + bindModuleExportsAssignment(node); + break; + case SpecialPropertyAssignmentKind.PrototypeProperty: + bindPrototypePropertyAssignment(node); + break; + case SpecialPropertyAssignmentKind.ThisProperty: + bindThisPropertyAssignment(node); + break; } } return checkStrictModeBinaryExpression(node); @@ -1038,6 +1057,13 @@ namespace ts { bindExportAssignment(node); } + function bindThisPropertyAssignment(node: BinaryExpression) { + if (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) { + container.symbol.members = container.symbol.members || {}; + declareClassMember(node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + } + } + function bindPrototypePropertyAssignment(node: BinaryExpression) { // We saw a node of the form 'x.prototype.y = z'. // This does two things: turns 'x' into a constructor function, and @@ -1054,16 +1080,20 @@ namespace ts { // The function is now a constructor rather than a normal function if (!funcSymbol.inferredConstructor) { - funcSymbol.flags = (funcSymbol.flags | SymbolFlags.Class) & ~SymbolFlags.Function; + declareSymbol(container.locals, funcSymbol, funcSymbol.valueDeclaration, SymbolFlags.Class, SymbolFlags.None); + // funcSymbol.flags = (funcSymbol.flags | SymbolFlags.Class) & ~SymbolFlags.Function; funcSymbol.members = funcSymbol.members || {}; funcSymbol.members["__constructor"] = funcSymbol; funcSymbol.inferredConstructor = true; } - // Get 'y', the property name, and add it to the type of the class - let propertyName = (node.left).name; - let prototypeSymbol = declareSymbol(funcSymbol.members, funcSymbol, (node.left).expression, SymbolFlags.HasMembers, SymbolFlags.None); + // Declare the 'prototype' member of the function + let prototypeSymbol = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); + + // Declare the property on the prototype symbol declareSymbol(prototypeSymbol.members, prototypeSymbol, node.left, SymbolFlags.Method, SymbolFlags.None); + // and on the class type + declareSymbol(funcSymbol.members, funcSymbol, node.left, SymbolFlags.Method, SymbolFlags.PropertyExcludes); } function bindCallExpression(node: CallExpression) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f0bdd48afa7..fb7040a96ab 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2576,9 +2576,16 @@ namespace ts { if (declaration.kind === SyntaxKind.BinaryExpression) { return links.type = checkExpression((declaration).right); } - // Handle exports.p = expr if (declaration.kind === SyntaxKind.PropertyAccessExpression) { - return checkExpressionCached((declaration.parent).right); + if (declaration.parent.kind === SyntaxKind.BinaryExpression) { + // Handle exports.p = expr or this.p = expr or className.prototype.method = expr + return links.type = checkExpression((declaration.parent).right); + } + else { + // Declaration for className.prototype in inferred JS class + let type = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, undefined, undefined); + return links.type = type; + } } // Handle variable, parameter or property if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { @@ -3799,8 +3806,15 @@ namespace ts { default: if (declaration.symbol.inferredConstructor) { kind = SignatureKind.Construct; - let proto = declaration.symbol.members["prototype"]; - returnType = createAnonymousType(createSymbol(SymbolFlags.None, "__jsClass"), proto.members, emptyArray, emptyArray, undefined, undefined); + let members = createSymbolTable(emptyArray); + // Collect methods declared with className.protoype.methodName = ... + let proto = declaration.symbol.exports["prototype"]; + if (proto) { + mergeSymbolTable(members, proto.members); + } + // Collect properties defined in the constructor by this.propName = ... + mergeSymbolTable(members, declaration.symbol.members); + returnType = createAnonymousType(declaration.symbol, members, emptyArray, emptyArray, undefined, undefined); } else { kind = SignatureKind.Call; @@ -3846,8 +3860,8 @@ namespace ts { break; case SyntaxKind.PropertyAccessExpression: - // Class inference from ClassName.prototype.methodName = expr - return getSignaturesOfType(checkExpressionCached((node.parent).right), SignatureKind.Call); + result = getSignaturesOfType(checkExpressionCached((node.parent).right), SignatureKind.Call); + break; } } return result; @@ -6957,7 +6971,10 @@ namespace ts { let operator = binaryExpression.operatorToken.kind; if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) { // In an assignment expression, the right operand is contextually typed by the type of the left operand. - if (node === binaryExpression.right) { + // In JS files where a special assignment is taking place, don't contextually type the RHS to avoid + // incorrectly assuming a circular 'any' (the type of the LHS is determined by the RHS) + if (node === binaryExpression.right && + !(node.parserContextFlags & ParserContextFlags.JavaScriptFile && getSpecialPropertyAssignmentKind(binaryExpression))) { return checkExpression(binaryExpression.left); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5232209e7d1..00375f8a574 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2013,6 +2013,19 @@ namespace ts { // It is optional because in contextual signature instantiation, nothing fails } + /* @internal */ + export const enum SpecialPropertyAssignmentKind { + None, + /// exports.name = expr + ExportsProperty, + /// module.exports = expr + ModuleExports, + /// className.prototype.name = expr + PrototypeProperty, + /// this.name = expr + ThisProperty + } + export interface DiagnosticMessage { key: string; category: DiagnosticCategory; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 05184e29f58..cb72e87bb94 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1057,6 +1057,42 @@ namespace ts { (expression).arguments[0].kind === SyntaxKind.StringLiteral; } + /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property + /// assignments we treat as special in the binder + export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind { + if (expression.kind !== SyntaxKind.BinaryExpression) { + return SpecialPropertyAssignmentKind.None; + } + const expr = expression; + if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || expr.left.kind !== SyntaxKind.PropertyAccessExpression) { + return SpecialPropertyAssignmentKind.None; + } + const lhs = expr.left; + if (lhs.expression.kind === SyntaxKind.Identifier) { + const lhsId = lhs.expression; + if (lhsId.text === "exports") { + // exports.name = expr + return SpecialPropertyAssignmentKind.ExportsProperty; + } + else if (lhsId.text === "module" && lhs.name.text === "exports") { + // module.exports = expr + return SpecialPropertyAssignmentKind.ModuleExports; + } + } + else if (lhs.expression.kind === SyntaxKind.ThisKeyword) { + return SpecialPropertyAssignmentKind.ThisProperty; + } + else if (lhs.expression.kind === SyntaxKind.PropertyAccessExpression) { + // chained dot, e.g. x.y.z = expr; this var is the 'x.y' part + let innerPropertyAccess = lhs.expression; + if (innerPropertyAccess.expression.kind === SyntaxKind.Identifier && innerPropertyAccess.name.text === "prototype") { + return SpecialPropertyAssignmentKind.PrototypeProperty; + } + } + + return SpecialPropertyAssignmentKind.None; + } + /** * Returns true if the node is an assignment to a property on the identifier 'exports'. * This function does not test if the node is in a JavaScript file or not. diff --git a/tests/cases/fourslash/javaScriptPrototype1.ts b/tests/cases/fourslash/javaScriptPrototype1.ts index 0dec8d721d6..0473d18aae8 100644 --- a/tests/cases/fourslash/javaScriptPrototype1.ts +++ b/tests/cases/fourslash/javaScriptPrototype1.ts @@ -11,26 +11,36 @@ //// //// var m = new myCtor(10); //// m/*1*/ -//// var x = m.foo(); -//// x/*2*/ -//// var y = m.bar(); -//// y/*3*/ +//// var a = m.foo; +//// a/*2*/ +//// var b = a(); +//// b/*3*/ +//// var c = m.bar(); +//// c/*4*/ + +// Members of the class instance goTo.marker('1'); edit.insert('.'); verify.memberListContains('foo', undefined, undefined, 'method'); -edit.insert('foo'); - -edit.backspace(); +verify.memberListContains('bar', undefined, undefined, 'method'); edit.backspace(); +// Members of a class method (1) goTo.marker('2'); edit.insert('.'); +verify.memberListContains('length', undefined, undefined, 'property'); +edit.backspace(); + +// Members of the invocation of a class method (1) +goTo.marker('3'); +edit.insert('.'); verify.memberListContains('toFixed', undefined, undefined, 'method'); verify.not.memberListContains('substr', undefined, undefined, 'method'); edit.backspace(); -goTo.marker('3'); +// Members of the invocation of a class method (2) +goTo.marker('4'); edit.insert('.'); verify.memberListContains('substr', undefined, undefined, 'method'); verify.not.memberListContains('toFixed', undefined, undefined, 'method'); diff --git a/tests/cases/fourslash/javaScriptPrototype2.ts b/tests/cases/fourslash/javaScriptPrototype2.ts new file mode 100644 index 00000000000..ab6afff3d2c --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype2.ts @@ -0,0 +1,36 @@ +/// + +// Assignments to 'this' in the constructorish body create +// properties with those names + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// this.qua = 10; +//// } +//// myCtor.prototype.foo = function() { return 32 }; +//// myCtor.prototype.bar = function() { return '' }; +//// +//// var m = new myCtor(10); +//// m/*1*/ +//// var x = m.qua; +//// x/*2*/ +//// myCtor/*3*/ + +// Verify the instance property exists +goTo.marker('1'); +edit.insert('.'); +verify.completionListContains('qua', undefined, undefined, 'property'); +edit.backspace(); + +// Verify the type of the instance property +goTo.marker('2'); +edit.insert('.'); +verify.completionListContains('toFixed', undefined, undefined, 'method'); + +goTo.marker('3'); +edit.insert('.'); +// Make sure symbols don't leak out into the constructor +verify.completionListContains('qua', undefined, undefined, 'warning'); +verify.completionListContains('foo', undefined, undefined, 'warning'); +verify.completionListContains('bar', undefined, undefined, 'warning'); diff --git a/tests/cases/fourslash/javaScriptPrototype3.ts b/tests/cases/fourslash/javaScriptPrototype3.ts new file mode 100644 index 00000000000..900a39ddce9 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype3.ts @@ -0,0 +1,40 @@ +/// + +// ES6 classes can extend from JS classes + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// this.qua = 10; +//// } +//// myCtor.prototype.foo = function() { return 32 }; +//// myCtor.prototype.bar = function() { return '' }; +//// +//// class MyClass extends myCtor { +//// fn() { +//// this/*1*/ +//// let y = super.foo(); +//// y; +//// } +//// } +//// var n = new MyClass(3); +//// n/*2*/; + +goTo.marker('1'); +edit.insert('.'); +// Current class method +verify.completionListContains('fn', undefined, undefined, 'method'); +// Base class method +verify.completionListContains('foo', undefined, undefined, 'method'); +// Base class instance property +verify.completionListContains('qua', undefined, undefined, 'property'); +edit.backspace(); + +// Derived class instance from outside the class +goTo.marker('2'); +edit.insert('.'); +verify.completionListContains('fn', undefined, undefined, 'method'); +// Base class method +verify.completionListContains('foo', undefined, undefined, 'method'); +// Base class instance property +verify.completionListContains('qua', undefined, undefined, 'property'); diff --git a/tests/cases/fourslash/javaScriptPrototype4.ts b/tests/cases/fourslash/javaScriptPrototype4.ts new file mode 100644 index 00000000000..78eab19733a --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype4.ts @@ -0,0 +1,36 @@ +/// + +// Check for any odd symbol leakage + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// this.qua = 10; +//// } +//// myCtor.prototype.foo = function() { return 32 }; +//// myCtor.prototype.bar = function() { return '' }; +//// +//// myCtor/*1*/ + +goTo.marker('1'); +edit.insert('.'); + +// Check members of the function +verify.completionListContains('prototype', undefined, undefined, 'property'); +verify.completionListContains('foo', undefined, undefined, 'warning'); +verify.completionListContains('bar', undefined, undefined, 'warning'); +verify.completionListContains('qua', undefined, undefined, 'warning'); + +// Check members of function.prototype +edit.insert('prototype.'); +debugger; +debug.printMemberListMembers(); +verify.completionListContains('foo', undefined, undefined, 'method'); +verify.completionListContains('bar', undefined, undefined, 'method'); +verify.completionListContains('qua', undefined, undefined, 'warning'); +verify.completionListContains('prototype', undefined, undefined, 'warning'); + +// debug.printErrorList(); +// debug.printCurrentQuickInfo(); +// edit.insert('.'); +// verify.completionListContains('toFixed', undefined, undefined, 'method'); From a3a5c1619d6371cd9b093f71ab83abc1d485d856 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 30 Oct 2015 12:35:20 -0700 Subject: [PATCH 04/75] Human-readable fourslash debug output for completion lists / quickinfo --- src/harness/fourslash.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index dd2dde6989c..8564714801a 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1265,7 +1265,7 @@ namespace FourSlash { public printCurrentQuickInfo() { let quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); - Harness.IO.log(JSON.stringify(quickInfo)); + Harness.IO.log("Quick Info: " + quickInfo.displayParts.map(part => part.text).join("")); } public printErrorList() { @@ -1307,12 +1307,26 @@ namespace FourSlash { public printMemberListMembers() { let members = this.getMemberListAtCaret(); - Harness.IO.log(JSON.stringify(members)); + this.printMembersOrCompletions(members); } public printCompletionListMembers() { let completions = this.getCompletionListAtCaret(); - Harness.IO.log(JSON.stringify(completions)); + this.printMembersOrCompletions(completions); + } + + private printMembersOrCompletions(info: ts.CompletionInfo) { + function pad(s: string, length: number) { + return s + new Array(length - s.length + 1).join(" "); + } + function max(arr: T[], selector: (x: T) => number): number { + return arr.reduce((prev, x) => Math.max(prev, selector(x)), 0); + } + let longestNameLength = max(info.entries, m => m.name.length); + let longestKindLength = max(info.entries, m => m.kind.length); + info.entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0); + let membersString = info.entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers}`).join("\n"); + Harness.IO.log(membersString); } public printReferences() { From eaeeb1f7624f9be5287544659debdbda40df8824 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 9 Nov 2015 15:19:41 -0800 Subject: [PATCH 05/75] Fix TC --- tests/cases/fourslash/javaScriptPrototype4.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/cases/fourslash/javaScriptPrototype4.ts b/tests/cases/fourslash/javaScriptPrototype4.ts index 78eab19733a..f78bf52438b 100644 --- a/tests/cases/fourslash/javaScriptPrototype4.ts +++ b/tests/cases/fourslash/javaScriptPrototype4.ts @@ -23,14 +23,9 @@ verify.completionListContains('qua', undefined, undefined, 'warning'); // Check members of function.prototype edit.insert('prototype.'); -debugger; debug.printMemberListMembers(); verify.completionListContains('foo', undefined, undefined, 'method'); verify.completionListContains('bar', undefined, undefined, 'method'); verify.completionListContains('qua', undefined, undefined, 'warning'); verify.completionListContains('prototype', undefined, undefined, 'warning'); -// debug.printErrorList(); -// debug.printCurrentQuickInfo(); -// edit.insert('.'); -// verify.completionListContains('toFixed', undefined, undefined, 'method'); From fb83ee0a3036687115f505d621a8022eaca95e07 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 20 Nov 2015 10:59:13 -0800 Subject: [PATCH 06/75] WIP --- src/compiler/binder.ts | 20 ++++--- src/compiler/checker.ts | 5 +- src/compiler/utilities.ts | 58 ------------------- tests/cases/fourslash/javaScriptPrototype4.ts | 1 - 4 files changed, 16 insertions(+), 68 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 9bd51f0c763..f91cf107749 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -635,7 +635,6 @@ namespace ts { function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) { let symbol = createSymbol(symbolFlags, name); addDeclarationToSymbol(symbol, node, symbolFlags); - return symbol; } function bindBlockScopedDeclaration(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { @@ -889,6 +888,11 @@ namespace ts { case SpecialPropertyAssignmentKind.ThisProperty: bindThisPropertyAssignment(node); break; + case SpecialPropertyAssignmentKind.None: + // Nothing to do + break; + default: + Debug.fail("Unknown special property assignment kind"); } } return checkStrictModeBinaryExpression(node); @@ -1080,19 +1084,19 @@ namespace ts { // The function is now a constructor rather than a normal function if (!funcSymbol.inferredConstructor) { + // Have the binder set up all the related class symbols for us declareSymbol(container.locals, funcSymbol, funcSymbol.valueDeclaration, SymbolFlags.Class, SymbolFlags.None); - // funcSymbol.flags = (funcSymbol.flags | SymbolFlags.Class) & ~SymbolFlags.Function; - funcSymbol.members = funcSymbol.members || {}; + // funcSymbol.members = funcSymbol.members || {}; funcSymbol.members["__constructor"] = funcSymbol; funcSymbol.inferredConstructor = true; } - // Declare the 'prototype' member of the function - let prototypeSymbol = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); + // Get the exports of the class so we can add the method to it + let funcExports = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); - // Declare the property on the prototype symbol - declareSymbol(prototypeSymbol.members, prototypeSymbol, node.left, SymbolFlags.Method, SymbolFlags.None); - // and on the class type + // Declare the method + declareSymbol(funcExports.members, funcExports, node.left, SymbolFlags.Method, SymbolFlags.None); + // and on the members of the function so it appears in 'prototype' declareSymbol(funcSymbol.members, funcSymbol, node.left, SymbolFlags.Method, SymbolFlags.PropertyExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fb7040a96ab..18a878ae91b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2577,9 +2577,11 @@ namespace ts { return links.type = checkExpression((declaration).right); } if (declaration.kind === SyntaxKind.PropertyAccessExpression) { + // Declarations only exist for property access expressions for certain + // special assignment kinds if (declaration.parent.kind === SyntaxKind.BinaryExpression) { // Handle exports.p = expr or this.p = expr or className.prototype.method = expr - return links.type = checkExpression((declaration.parent).right); + return links.type = checkExpressionCached((declaration.parent).right); } else { // Declaration for className.prototype in inferred JS class @@ -3860,6 +3862,7 @@ namespace ts { break; case SyntaxKind.PropertyAccessExpression: + // Inferred class method result = getSignaturesOfType(checkExpressionCached((node.parent).right), SignatureKind.Call); break; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index cb72e87bb94..603f5a3d93c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1093,64 +1093,6 @@ namespace ts { return SpecialPropertyAssignmentKind.None; } - /** - * Returns true if the node is an assignment to a property on the identifier 'exports'. - * This function does not test if the node is in a JavaScript file or not. - */ - export function isExportsPropertyAssignment(expression: Node): boolean { - // of the form 'exports.name = expr' where 'name' and 'expr' are arbitrary - return isInJavaScriptFile(expression) && - (expression.kind === SyntaxKind.BinaryExpression) && - ((expression).operatorToken.kind === SyntaxKind.EqualsToken) && - ((expression).left.kind === SyntaxKind.PropertyAccessExpression) && - (((expression).left).expression.kind === SyntaxKind.Identifier) && - (((((expression).left).expression)).text === "exports"); - } - - /** - * Returns true if the node is an assignment to the property access expression 'module.exports'. - * This function does not test if the node is in a JavaScript file or not. - */ - export function isModuleExportsAssignment(expression: Node): boolean { - // of the form 'module.exports = expr' where 'expr' is arbitrary - return isInJavaScriptFile(expression) && - (expression.kind === SyntaxKind.BinaryExpression) && - ((expression).operatorToken.kind === SyntaxKind.EqualsToken) && - ((expression).left.kind === SyntaxKind.PropertyAccessExpression) && - (((expression).left).expression.kind === SyntaxKind.Identifier) && - (((((expression).left).expression)).text === "module") && - (((expression).left).name.text === "exports"); - } - - /** - * Returns true if this expression is an assignment to the given named property - */ - function isAssignmentToProperty(expression: Node, name?: string): expression is BinaryExpression { - return (expression.kind === SyntaxKind.BinaryExpression) && - ((expression).operatorToken.kind === SyntaxKind.EqualsToken) && - isNamedPropertyAccess((expression).left, name); - } - - /** - * Returns true if this expression is a PropertyAccessExpression where the property name is the provided name - */ - function isNamedPropertyAccess(expression: Node, name?: string): expression is PropertyAccessExpression { - return expression.kind === SyntaxKind.PropertyAccessExpression && - (!name || (expression).name.text === name); - } - - /** - * Returns true if the node is an assignment in the form 'id1.prototype.id2 = expr' where id1 and id2 - * are any identifier. - * This function does not test if the node is in a JavaScript file or not. - */ - export function isPrototypePropertyAssignment(expression: Node): expression is BinaryExpression { - return isAssignmentToProperty(expression) && - isNamedPropertyAccess(expression.left) && - isNamedPropertyAccess((expression.left).expression, "prototype") && - ((expression.left).expression).expression.kind === SyntaxKind.Identifier; - } - export function getExternalModuleName(node: Node): Expression { if (node.kind === SyntaxKind.ImportDeclaration) { return (node).moduleSpecifier; diff --git a/tests/cases/fourslash/javaScriptPrototype4.ts b/tests/cases/fourslash/javaScriptPrototype4.ts index f78bf52438b..3ed723740b4 100644 --- a/tests/cases/fourslash/javaScriptPrototype4.ts +++ b/tests/cases/fourslash/javaScriptPrototype4.ts @@ -23,7 +23,6 @@ verify.completionListContains('qua', undefined, undefined, 'warning'); // Check members of function.prototype edit.insert('prototype.'); -debug.printMemberListMembers(); verify.completionListContains('foo', undefined, undefined, 'method'); verify.completionListContains('bar', undefined, undefined, 'method'); verify.completionListContains('qua', undefined, undefined, 'warning'); From c4b0b62bfc694928ed79858d8e9bcb8f2790bb05 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 1 Dec 2015 15:06:53 -0800 Subject: [PATCH 07/75] Merge fixup --- src/compiler/binder.ts | 10 +++++----- src/compiler/checker.ts | 21 ++++++++++++++------- src/compiler/utilities.ts | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7f0fd2fb3fa..86fcc809d58 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1178,8 +1178,8 @@ namespace ts { case SyntaxKind.Identifier: return checkStrictModeIdentifier(node); case SyntaxKind.BinaryExpression: - if (isJavaScriptFile) { - let specialKind = getSpecialPropertyAssignmentKind(node); + if (isInJavaScriptFile(node)) { + const specialKind = getSpecialPropertyAssignmentKind(node); switch (specialKind) { case SpecialPropertyAssignmentKind.ExportsProperty: bindExportsPropertyAssignment(node); @@ -1378,11 +1378,11 @@ namespace ts { // This does two things: turns 'x' into a constructor function, and // adds a member 'y' to the result of that constructor function // Get 'x', the class - let classId = ((node.left).expression).expression; + const classId = ((node.left).expression).expression; // Look up the function in the local scope, since prototype assignments should immediately // follow the function declaration - let funcSymbol = container.locals[classId.text]; + const funcSymbol = container.locals[classId.text]; if (!funcSymbol) { return; } @@ -1397,7 +1397,7 @@ namespace ts { } // Get the exports of the class so we can add the method to it - let funcExports = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); + const funcExports = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); // Declare the method declareSymbol(funcExports.members, funcExports, node.left, SymbolFlags.Method, SymbolFlags.None); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 29e31a84a23..94c13fd1f3f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -123,8 +123,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, undefined, 0, false, false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, undefined, 0, false, false); + const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const globals: SymbolTable = {}; @@ -2661,7 +2661,7 @@ namespace ts { } else { // Declaration for className.prototype in inferred JS class - let type = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, undefined, undefined); + const type = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, undefined, undefined); return links.type = type; } } @@ -3930,9 +3930,9 @@ namespace ts { default: if (declaration.symbol.inferredConstructor) { kind = SignatureKind.Construct; - let members = createSymbolTable(emptyArray); + const members = createSymbolTable(emptyArray); // Collect methods declared with className.protoype.methodName = ... - let proto = declaration.symbol.exports["prototype"]; + const proto = declaration.symbol.exports["prototype"]; if (proto) { mergeSymbolTable(members, proto.members); } @@ -3954,7 +3954,7 @@ namespace ts { function getSignaturesOfSymbol(symbol: Symbol): Signature[] { if (!symbol) return emptyArray; - const result: Signature[] = []; + let result: Signature[] = []; for (let i = 0, len = symbol.declarations.length; i < len; i++) { const node = symbol.declarations[i]; switch (node.kind) { @@ -6841,7 +6841,14 @@ namespace ts { let container: Node; if (symbol.flags & SymbolFlags.Class) { // get parent of class declaration - container = getClassLikeDeclarationOfSymbol(symbol).parent; + const classDeclaration = getClassLikeDeclarationOfSymbol(symbol); + if (classDeclaration) { + container = classDeclaration.parent; + } + else { + // JS-inferred class; do nothing + return; + } } else { // nesting structure: diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 553c5bbeff0..cffc1e90a06 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1090,7 +1090,7 @@ namespace ts { } else if (lhs.expression.kind === SyntaxKind.PropertyAccessExpression) { // chained dot, e.g. x.y.z = expr; this var is the 'x.y' part - let innerPropertyAccess = lhs.expression; + const innerPropertyAccess = lhs.expression; if (innerPropertyAccess.expression.kind === SyntaxKind.Identifier && innerPropertyAccess.name.text === "prototype") { return SpecialPropertyAssignmentKind.PrototypeProperty; } From fabc43d0d401795531f7597eae70d209d0bb0e33 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 4 Dec 2015 14:11:56 -0800 Subject: [PATCH 08/75] JS Prototypes WIP --- src/compiler/binder.ts | 33 +++++++++++---------------------- src/compiler/types.ts | 1 - 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 86fcc809d58..eedcd456b84 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1367,42 +1367,31 @@ namespace ts { } function bindThisPropertyAssignment(node: BinaryExpression) { + // Declare a 'member' in case it turns out the container was an ES5 class if (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) { container.symbol.members = container.symbol.members || {}; - declareClassMember(node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } } function bindPrototypePropertyAssignment(node: BinaryExpression) { - // We saw a node of the form 'x.prototype.y = z'. - // This does two things: turns 'x' into a constructor function, and - // adds a member 'y' to the result of that constructor function - // Get 'x', the class - const classId = ((node.left).expression).expression; + // We saw a node of the form 'x.prototype.y = z'. Declare a 'member' y on x if x was a function. - // Look up the function in the local scope, since prototype assignments should immediately + // Look up the function in the local scope, since prototype assignments should // follow the function declaration + const classId = ((node.left).expression).expression; const funcSymbol = container.locals[classId.text]; - if (!funcSymbol) { + if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function)) { return; } - // The function is now a constructor rather than a normal function - if (!funcSymbol.inferredConstructor) { - // Have the binder set up all the related class symbols for us - declareSymbol(container.locals, funcSymbol, funcSymbol.valueDeclaration, SymbolFlags.Class, SymbolFlags.None); - // funcSymbol.members = funcSymbol.members || {}; - funcSymbol.members["__constructor"] = funcSymbol; - funcSymbol.inferredConstructor = true; + // Set up the members collection if it doesn't exist already + if (!funcSymbol.members) { + funcSymbol.members = {}; } - // Get the exports of the class so we can add the method to it - const funcExports = declareSymbol(funcSymbol.exports, funcSymbol, (node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None); - - // Declare the method - declareSymbol(funcExports.members, funcExports, node.left, SymbolFlags.Method, SymbolFlags.None); - // and on the members of the function so it appears in 'prototype' - declareSymbol(funcSymbol.members, funcSymbol, node.left, SymbolFlags.Method, SymbolFlags.PropertyExcludes); + // Declare the method/property + declareSymbol(funcSymbol.members, funcSymbol, node.left, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } function bindCallExpression(node: CallExpression) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index daec64c0dac..16e5e4b57fe 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1985,7 +1985,6 @@ namespace ts { /* @internal */ parent?: Symbol; // Parent symbol /* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol /* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums - /* @internal */ inferredConstructor?: boolean; // A function promoted to constructor as the result of a prototype property assignment } /* @internal */ From fcd00a59d2b213bf469ed891e95ca9ab0d6c73a4 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 4 Dec 2015 14:58:32 -0800 Subject: [PATCH 09/75] Simplified JS prototype class inference --- src/compiler/checker.ts | 82 ++++++------------- src/compiler/types.ts | 1 - src/services/services.ts | 1 - tests/cases/fourslash/javaScriptPrototype1.ts | 4 +- tests/cases/fourslash/javaScriptPrototype3.ts | 40 --------- tests/cases/fourslash/javaScriptPrototype4.ts | 9 -- 6 files changed, 27 insertions(+), 110 deletions(-) delete mode 100644 tests/cases/fourslash/javaScriptPrototype3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 22b45926cad..dc2d6649013 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -123,8 +123,8 @@ namespace ts { const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const anySignature = createSignature(undefined, undefined, emptyArray, undefined, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); - const unknownSignature = createSignature(undefined, undefined, emptyArray, undefined, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); + const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false); const globals: SymbolTable = {}; @@ -3374,13 +3374,12 @@ namespace ts { resolveObjectTypeMembers(type, source, typeParameters, typeArguments); } - function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], kind: SignatureKind, + function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[], resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature { const sig = new Signature(checker); sig.declaration = declaration; sig.typeParameters = typeParameters; sig.parameters = parameters; - sig.kind = kind; sig.resolvedReturnType = resolvedReturnType; sig.typePredicate = typePredicate; sig.minArgumentCount = minArgumentCount; @@ -3390,13 +3389,13 @@ namespace ts { } function cloneSignature(sig: Signature): Signature { - return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.kind, sig.resolvedReturnType, sig.typePredicate, + return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals); } function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { if (!hasClassBaseType(classType)) { - return [createSignature(undefined, classType.localTypeParameters, emptyArray, SignatureKind.Construct, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; + return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)]; } const baseConstructorType = getBaseConstructorTypeOfClass(classType); const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); @@ -3932,33 +3931,7 @@ namespace ts { } } - let kind: SignatureKind; - switch (declaration.kind) { - case SyntaxKind.Constructor: - case SyntaxKind.ConstructSignature: - case SyntaxKind.ConstructorType: - kind = SignatureKind.Construct; - break; - default: - if (declaration.symbol.inferredConstructor) { - kind = SignatureKind.Construct; - const members = createSymbolTable(emptyArray); - // Collect methods declared with className.protoype.methodName = ... - const proto = declaration.symbol.exports["prototype"]; - if (proto) { - mergeSymbolTable(members, proto.members); - } - // Collect properties defined in the constructor by this.propName = ... - mergeSymbolTable(members, declaration.symbol.members); - returnType = createAnonymousType(declaration.symbol, members, emptyArray, emptyArray, undefined, undefined); - } - else { - kind = SignatureKind.Call; - } - break; - } - - links.resolvedSignature = createSignature(declaration, typeParameters, parameters, kind, returnType, typePredicate, + links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals); } return links.resolvedSignature; @@ -3966,7 +3939,7 @@ namespace ts { function getSignaturesOfSymbol(symbol: Symbol): Signature[] { if (!symbol) return emptyArray; - let result: Signature[] = []; + const result: Signature[] = []; for (let i = 0, len = symbol.declarations.length; i < len; i++) { const node = symbol.declarations[i]; switch (node.kind) { @@ -3993,12 +3966,6 @@ namespace ts { } } result.push(getSignatureFromDeclaration(node)); - break; - - case SyntaxKind.PropertyAccessExpression: - // Inferred class method - result = getSignaturesOfType(checkExpressionCached((node.parent).right), SignatureKind.Call); - break; } } return result; @@ -4081,7 +4048,7 @@ namespace ts { // object type literal or interface (using the new keyword). Each way of declaring a constructor // will result in a different declaration kind. if (!signature.isolatedSignatureType) { - const isConstructor = signature.kind === SignatureKind.Construct; + const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature; const type = createObjectType(TypeFlags.Anonymous | TypeFlags.FromSignature); type.members = emptySymbols; type.properties = emptyArray; @@ -4784,7 +4751,6 @@ namespace ts { } const result = createSignature(signature.declaration, freshTypeParameters, instantiateList(signature.parameters, mapper, instantiateSymbol), - signature.kind, instantiateType(signature.resolvedReturnType, mapper), freshTypePredicate, signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals); @@ -6838,14 +6804,7 @@ namespace ts { let container: Node; if (symbol.flags & SymbolFlags.Class) { // get parent of class declaration - const classDeclaration = getClassLikeDeclarationOfSymbol(symbol); - if (classDeclaration) { - container = classDeclaration.parent; - } - else { - // JS-inferred class; do nothing - return; - } + container = getClassLikeDeclarationOfSymbol(symbol).parent; } else { // nesting structure: @@ -7189,10 +7148,7 @@ namespace ts { const operator = binaryExpression.operatorToken.kind; if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) { // In an assignment expression, the right operand is contextually typed by the type of the left operand. - // In JS files where a special assignment is taking place, don't contextually type the RHS to avoid - // incorrectly assuming a circular 'any' (the type of the LHS is determined by the RHS) - if (node === binaryExpression.right && - !(node.parserContextFlags & ParserContextFlags.JavaScriptFile && getSpecialPropertyAssignmentKind(binaryExpression))) { + if (node === binaryExpression.right) { return checkExpression(binaryExpression.left); } } @@ -9676,9 +9632,21 @@ namespace ts { return voidType; } if (node.kind === SyntaxKind.NewExpression) { - if (signature.kind === SignatureKind.Call) { - // When resolved signature is a call signature (and not a construct signature) the result type is any - if (compilerOptions.noImplicitAny) { + const declaration = signature.declaration; + + if (declaration && + declaration.kind !== SyntaxKind.Constructor && + declaration.kind !== SyntaxKind.ConstructSignature && + declaration.kind !== SyntaxKind.ConstructorType) { + + // When resolved signature is a call signature (and not a construct signature) the result type is any, unless + // the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations + // in a JS file + const funcSymbol = checkExpression(node.expression).symbol; + if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) { + return createAnonymousType(undefined, funcSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + } + else if (compilerOptions.noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } return anyType; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 169ce4acfda..34e862768d0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2237,7 +2237,6 @@ namespace ts { declaration: SignatureDeclaration; // Originating declaration typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters - kind: SignatureKind; // Call or Construct typePredicate?: TypePredicate; // Type predicate /* @internal */ resolvedReturnType: Type; // Resolved return type diff --git a/src/services/services.ts b/src/services/services.ts index e145406ac18..4e0a0265b91 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -741,7 +741,6 @@ namespace ts { declaration: SignatureDeclaration; typeParameters: TypeParameter[]; parameters: Symbol[]; - kind: SignatureKind; resolvedReturnType: Type; minArgumentCount: number; hasRestParameter: boolean; diff --git a/tests/cases/fourslash/javaScriptPrototype1.ts b/tests/cases/fourslash/javaScriptPrototype1.ts index 0473d18aae8..c9c454cfb2c 100644 --- a/tests/cases/fourslash/javaScriptPrototype1.ts +++ b/tests/cases/fourslash/javaScriptPrototype1.ts @@ -22,8 +22,8 @@ // Members of the class instance goTo.marker('1'); edit.insert('.'); -verify.memberListContains('foo', undefined, undefined, 'method'); -verify.memberListContains('bar', undefined, undefined, 'method'); +verify.memberListContains('foo', undefined, undefined, 'property'); +verify.memberListContains('bar', undefined, undefined, 'property'); edit.backspace(); // Members of a class method (1) diff --git a/tests/cases/fourslash/javaScriptPrototype3.ts b/tests/cases/fourslash/javaScriptPrototype3.ts deleted file mode 100644 index 900a39ddce9..00000000000 --- a/tests/cases/fourslash/javaScriptPrototype3.ts +++ /dev/null @@ -1,40 +0,0 @@ -/// - -// ES6 classes can extend from JS classes - -// @allowNonTsExtensions: true -// @Filename: myMod.js -//// function myCtor(x) { -//// this.qua = 10; -//// } -//// myCtor.prototype.foo = function() { return 32 }; -//// myCtor.prototype.bar = function() { return '' }; -//// -//// class MyClass extends myCtor { -//// fn() { -//// this/*1*/ -//// let y = super.foo(); -//// y; -//// } -//// } -//// var n = new MyClass(3); -//// n/*2*/; - -goTo.marker('1'); -edit.insert('.'); -// Current class method -verify.completionListContains('fn', undefined, undefined, 'method'); -// Base class method -verify.completionListContains('foo', undefined, undefined, 'method'); -// Base class instance property -verify.completionListContains('qua', undefined, undefined, 'property'); -edit.backspace(); - -// Derived class instance from outside the class -goTo.marker('2'); -edit.insert('.'); -verify.completionListContains('fn', undefined, undefined, 'method'); -// Base class method -verify.completionListContains('foo', undefined, undefined, 'method'); -// Base class instance property -verify.completionListContains('qua', undefined, undefined, 'property'); diff --git a/tests/cases/fourslash/javaScriptPrototype4.ts b/tests/cases/fourslash/javaScriptPrototype4.ts index 3ed723740b4..81cb5fe3784 100644 --- a/tests/cases/fourslash/javaScriptPrototype4.ts +++ b/tests/cases/fourslash/javaScriptPrototype4.ts @@ -16,15 +16,6 @@ goTo.marker('1'); edit.insert('.'); // Check members of the function -verify.completionListContains('prototype', undefined, undefined, 'property'); verify.completionListContains('foo', undefined, undefined, 'warning'); verify.completionListContains('bar', undefined, undefined, 'warning'); verify.completionListContains('qua', undefined, undefined, 'warning'); - -// Check members of function.prototype -edit.insert('prototype.'); -verify.completionListContains('foo', undefined, undefined, 'method'); -verify.completionListContains('bar', undefined, undefined, 'method'); -verify.completionListContains('qua', undefined, undefined, 'warning'); -verify.completionListContains('prototype', undefined, undefined, 'warning'); - From c97dffff3b2590e92311fccf2bf3744599972370 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 7 Dec 2015 11:55:30 -0800 Subject: [PATCH 10/75] Support 'this' in inferred method bodies --- src/compiler/checker.ts | 17 ++++++++++++++++ tests/cases/fourslash/javaScriptPrototype3.ts | 20 +++++++++++++++++++ tests/cases/fourslash/javaScriptPrototype5.ts | 19 ++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/cases/fourslash/javaScriptPrototype3.ts create mode 100644 tests/cases/fourslash/javaScriptPrototype5.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dc2d6649013..79f514e7864 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6897,6 +6897,23 @@ namespace ts { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; } + + // If this is a function in a JS file, it might be a class method. Check if it's the RHS + // of a x.prototype.y = function [name]() { .... } + if (isInJavaScriptFile(node) && container.kind === SyntaxKind.FunctionExpression) { + if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) { + // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') + const className = (((container.parent as BinaryExpression) // x.protoype.y = f + .left as PropertyAccessExpression) // x.prototype.y + .expression as PropertyAccessExpression) // x.prototype + .expression; // x + const classSymbol = checkExpression(className).symbol; + if (classSymbol.members) { + return createAnonymousType(undefined, classSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + } + } + } + return anyType; } diff --git a/tests/cases/fourslash/javaScriptPrototype3.ts b/tests/cases/fourslash/javaScriptPrototype3.ts new file mode 100644 index 00000000000..7b3f63eca57 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype3.ts @@ -0,0 +1,20 @@ +/// + +// Inside an inferred method body, the type of 'this' is the class type + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// this.qua = 10; +//// } +//// myCtor.prototype.foo = function() { return this/**/; }; +//// myCtor.prototype.bar = function() { return '' }; +//// + +goTo.marker(); +edit.insert('.'); + +// Check members of the function +verify.completionListContains('foo', undefined, undefined, 'property'); +verify.completionListContains('bar', undefined, undefined, 'property'); +verify.completionListContains('qua', undefined, undefined, 'property'); diff --git a/tests/cases/fourslash/javaScriptPrototype5.ts b/tests/cases/fourslash/javaScriptPrototype5.ts new file mode 100644 index 00000000000..a0125e47512 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype5.ts @@ -0,0 +1,19 @@ +/// + +// No prototype assignments are needed to enable class inference + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor() { +//// this.foo = 'hello'; +//// this.bar = 10; +//// } +//// let x = new myCtor(); +//// x/**/ + +goTo.marker(); +edit.insert('.'); + +// Check members of the function +verify.completionListContains('foo', undefined, undefined, 'property'); +verify.completionListContains('bar', undefined, undefined, 'property'); From 2cc6c4cc289c1e6f8d622a8c5da616357d1230f0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:28:35 -0800 Subject: [PATCH 11/75] Fixed test to explicitly have return type annotation. --- .../types/stringLiteral/stringLiteralTypesOverloads01.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts index d88167eaeff..00441134405 100644 --- a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts @@ -9,7 +9,7 @@ function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; -function getFalsyPrimitive(x: PrimitiveName) { +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } From 5ef8a306422abded21cb09e87f6b4cada7d4fb2d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:34:20 -0800 Subject: [PATCH 12/75] Accepted baselines. --- .../reference/stringLiteralTypesOverloads01.errors.txt | 8 ++++---- .../baselines/reference/stringLiteralTypesOverloads01.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt index 1592427208b..0a3fdb91929 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(11,10): error TS2354: No best common type exists among return expressions. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(7,10): error TS2394: Overload signature is not compatible with function implementation. ==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts (1 errors) ==== @@ -9,12 +9,12 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(11, function getFalsyPrimitive(x: "number"): number; function getFalsyPrimitive(x: "boolean"): boolean; function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; + ~~~~~~~~~~~~~~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; - function getFalsyPrimitive(x: PrimitiveName) { - ~~~~~~~~~~~~~~~~~ -!!! error TS2354: No best common type exists among return expressions. + function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.js b/tests/baselines/reference/stringLiteralTypesOverloads01.js index 73dabd26fab..f3331c9f717 100644 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.js +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.js @@ -9,7 +9,7 @@ function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; function getFalsyPrimitive(x: "number" | "string"): number | string; function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; -function getFalsyPrimitive(x: PrimitiveName) { +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { if (x === "string") { return ""; } From 2c2b8be2386f5a29b085ecb489b22786b8acba03 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 14:53:05 -0800 Subject: [PATCH 13/75] Remove empty test. --- .../functions/conformanceFunctionOverloads.ts | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 tests/cases/conformance/functions/conformanceFunctionOverloads.ts diff --git a/tests/cases/conformance/functions/conformanceFunctionOverloads.ts b/tests/cases/conformance/functions/conformanceFunctionOverloads.ts deleted file mode 100644 index f1e08782a51..00000000000 --- a/tests/cases/conformance/functions/conformanceFunctionOverloads.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Function overloads do not emit code - -// Function overload signature with optional parameter - -// Function overload signature with optional parameter - -// Function overloads with generic and non-generic overloads - -// Function overloads whose only difference is returning different unconstrained generic parameters - -// Function overloads whose only difference is returning different constrained generic parameters - -// Function overloads that differ only by type parameter constraints - -// Function overloads with matching accessibility - -// Function overloads with matching export - -// Function overloads with more params than implementation signature - -// Function overloads where return types are same infinitely recursive type reference - From 820a2cb257ae3926b7752c69f0bf31959e4114bb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 15:03:58 -0800 Subject: [PATCH 14/75] Added some tests for overload compatibility. --- tests/cases/compiler/functionOverloads43.ts | 12 +++++++++++ tests/cases/compiler/functionOverloads44.ts | 22 +++++++++++++++++++++ tests/cases/compiler/functionOverloads45.ts | 22 +++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/cases/compiler/functionOverloads43.ts create mode 100644 tests/cases/compiler/functionOverloads44.ts create mode 100644 tests/cases/compiler/functionOverloads45.ts diff --git a/tests/cases/compiler/functionOverloads43.ts b/tests/cases/compiler/functionOverloads43.ts new file mode 100644 index 00000000000..8822fd86c1b --- /dev/null +++ b/tests/cases/compiler/functionOverloads43.ts @@ -0,0 +1,12 @@ +function foo(bar: { a:number }[]): number; +function foo(bar: { a:string }[]): string; +function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; +} + +var x = foo([{a: "str"}]); +var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/cases/compiler/functionOverloads44.ts b/tests/cases/compiler/functionOverloads44.ts new file mode 100644 index 00000000000..20a7ed540f0 --- /dev/null +++ b/tests/cases/compiler/functionOverloads44.ts @@ -0,0 +1,22 @@ +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Dog; +function foo1(bar: { a:string }[]): Animal; +function foo1([x]: { a:number | string }[]): Dog { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Cat | Dog; +function foo2([x]: { a:number | string }[]): Cat { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/cases/compiler/functionOverloads45.ts b/tests/cases/compiler/functionOverloads45.ts new file mode 100644 index 00000000000..6210bd13427 --- /dev/null +++ b/tests/cases/compiler/functionOverloads45.ts @@ -0,0 +1,22 @@ +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Cat; +function foo1(bar: { a:string }[]): Dog; +function foo1([x]: { a:number | string }[]): Animal { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Dog; +function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); \ No newline at end of file From 5d94e48e42a680eabb5969bb62047c6f9277a788 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 15:12:52 -0800 Subject: [PATCH 15/75] Accepted baselines. --- .../reference/conformanceFunctionOverloads.js | 37 ------- .../conformanceFunctionOverloads.symbols | 25 ----- .../conformanceFunctionOverloads.types | 25 ----- .../reference/functionOverloads43.errors.txt | 18 ++++ .../reference/functionOverloads43.js | 24 +++++ .../reference/functionOverloads44.js | 37 +++++++ .../reference/functionOverloads44.symbols | 81 ++++++++++++++++ .../reference/functionOverloads44.types | 97 +++++++++++++++++++ .../reference/functionOverloads45.errors.txt | 31 ++++++ .../reference/functionOverloads45.js | 37 +++++++ 10 files changed, 325 insertions(+), 87 deletions(-) delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.js delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.symbols delete mode 100644 tests/baselines/reference/conformanceFunctionOverloads.types create mode 100644 tests/baselines/reference/functionOverloads43.errors.txt create mode 100644 tests/baselines/reference/functionOverloads43.js create mode 100644 tests/baselines/reference/functionOverloads44.js create mode 100644 tests/baselines/reference/functionOverloads44.symbols create mode 100644 tests/baselines/reference/functionOverloads44.types create mode 100644 tests/baselines/reference/functionOverloads45.errors.txt create mode 100644 tests/baselines/reference/functionOverloads45.js diff --git a/tests/baselines/reference/conformanceFunctionOverloads.js b/tests/baselines/reference/conformanceFunctionOverloads.js deleted file mode 100644 index b245f6a2c91..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.js +++ /dev/null @@ -1,37 +0,0 @@ -//// [conformanceFunctionOverloads.ts] -// Function overloads do not emit code - -// Function overload signature with optional parameter - -// Function overload signature with optional parameter - -// Function overloads with generic and non-generic overloads - -// Function overloads whose only difference is returning different unconstrained generic parameters - -// Function overloads whose only difference is returning different constrained generic parameters - -// Function overloads that differ only by type parameter constraints - -// Function overloads with matching accessibility - -// Function overloads with matching export - -// Function overloads with more params than implementation signature - -// Function overloads where return types are same infinitely recursive type reference - - - -//// [conformanceFunctionOverloads.js] -// Function overloads do not emit code -// Function overload signature with optional parameter -// Function overload signature with optional parameter -// Function overloads with generic and non-generic overloads -// Function overloads whose only difference is returning different unconstrained generic parameters -// Function overloads whose only difference is returning different constrained generic parameters -// Function overloads that differ only by type parameter constraints -// Function overloads with matching accessibility -// Function overloads with matching export -// Function overloads with more params than implementation signature -// Function overloads where return types are same infinitely recursive type reference diff --git a/tests/baselines/reference/conformanceFunctionOverloads.symbols b/tests/baselines/reference/conformanceFunctionOverloads.symbols deleted file mode 100644 index a80814ea93e..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.symbols +++ /dev/null @@ -1,25 +0,0 @@ -=== tests/cases/conformance/functions/conformanceFunctionOverloads.ts === -// Function overloads do not emit code -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overloads with generic and non-generic overloads -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different unconstrained generic parameters -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different constrained generic parameters -No type information for this code. -No type information for this code.// Function overloads that differ only by type parameter constraints -No type information for this code. -No type information for this code.// Function overloads with matching accessibility -No type information for this code. -No type information for this code.// Function overloads with matching export -No type information for this code. -No type information for this code.// Function overloads with more params than implementation signature -No type information for this code. -No type information for this code.// Function overloads where return types are same infinitely recursive type reference -No type information for this code. -No type information for this code. -No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/conformanceFunctionOverloads.types b/tests/baselines/reference/conformanceFunctionOverloads.types deleted file mode 100644 index a80814ea93e..00000000000 --- a/tests/baselines/reference/conformanceFunctionOverloads.types +++ /dev/null @@ -1,25 +0,0 @@ -=== tests/cases/conformance/functions/conformanceFunctionOverloads.ts === -// Function overloads do not emit code -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overload signature with optional parameter -No type information for this code. -No type information for this code.// Function overloads with generic and non-generic overloads -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different unconstrained generic parameters -No type information for this code. -No type information for this code.// Function overloads whose only difference is returning different constrained generic parameters -No type information for this code. -No type information for this code.// Function overloads that differ only by type parameter constraints -No type information for this code. -No type information for this code.// Function overloads with matching accessibility -No type information for this code. -No type information for this code.// Function overloads with matching export -No type information for this code. -No type information for this code.// Function overloads with more params than implementation signature -No type information for this code. -No type information for this code.// Function overloads where return types are same infinitely recursive type reference -No type information for this code. -No type information for this code. -No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.errors.txt b/tests/baselines/reference/functionOverloads43.errors.txt new file mode 100644 index 00000000000..769bb467186 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/functionOverloads43.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/compiler/functionOverloads43.ts (1 errors) ==== + function foo(bar: { a:number }[]): number; + ~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo(bar: { a:string }[]): string; + function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; + } + + var x = foo([{a: "str"}]); + var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.js b/tests/baselines/reference/functionOverloads43.js new file mode 100644 index 00000000000..2bb4b61af14 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.js @@ -0,0 +1,24 @@ +//// [functionOverloads43.ts] +function foo(bar: { a:number }[]): number; +function foo(bar: { a:string }[]): string; +function foo([x]: { a:number | string }[]): string | number { + if (x) { + return x.a; + } + + return undefined; +} + +var x = foo([{a: "str"}]); +var y = foo([{a: 100}]); + +//// [functionOverloads43.js] +function foo(_a) { + var x = _a[0]; + if (x) { + return x.a; + } + return undefined; +} +var x = foo([{ a: "str" }]); +var y = foo([{ a: 100 }]); diff --git a/tests/baselines/reference/functionOverloads44.js b/tests/baselines/reference/functionOverloads44.js new file mode 100644 index 00000000000..916204d123c --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.js @@ -0,0 +1,37 @@ +//// [functionOverloads44.ts] +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Dog; +function foo1(bar: { a:string }[]): Animal; +function foo1([x]: { a:number | string }[]): Dog { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Cat | Dog; +function foo2([x]: { a:number | string }[]): Cat { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); + +//// [functionOverloads44.js] +function foo1(_a) { + var x = _a[0]; + return undefined; +} +function foo2(_a) { + var x = _a[0]; + return undefined; +} +var x1 = foo1([{ a: "str" }]); +var y1 = foo1([{ a: 100 }]); +var x2 = foo2([{ a: "str" }]); +var y2 = foo2([{ a: 100 }]); diff --git a/tests/baselines/reference/functionOverloads44.symbols b/tests/baselines/reference/functionOverloads44.symbols new file mode 100644 index 00000000000..3520777a835 --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.symbols @@ -0,0 +1,81 @@ +=== tests/cases/compiler/functionOverloads44.ts === +interface Animal { animal } +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>animal : Symbol(animal, Decl(functionOverloads44.ts, 0, 18)) + +interface Dog extends Animal { dog } +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>dog : Symbol(dog, Decl(functionOverloads44.ts, 1, 30)) + +interface Cat extends Animal { cat } +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) +>cat : Symbol(cat, Decl(functionOverloads44.ts, 2, 30)) + +function foo1(bar: { a:number }[]): Dog; +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 4, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 4, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + +function foo1(bar: { a:string }[]): Animal; +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 5, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 5, 20)) +>Animal : Symbol(Animal, Decl(functionOverloads44.ts, 0, 0)) + +function foo1([x]: { a:number | string }[]): Dog { +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>x : Symbol(x, Decl(functionOverloads44.ts, 6, 15)) +>a : Symbol(a, Decl(functionOverloads44.ts, 6, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + + return undefined; +>undefined : Symbol(undefined) +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 10, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 10, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) + +function foo2(bar: { a:string }[]): Cat | Dog; +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>bar : Symbol(bar, Decl(functionOverloads44.ts, 11, 14)) +>a : Symbol(a, Decl(functionOverloads44.ts, 11, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) +>Dog : Symbol(Dog, Decl(functionOverloads44.ts, 0, 27)) + +function foo2([x]: { a:number | string }[]): Cat { +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>x : Symbol(x, Decl(functionOverloads44.ts, 12, 15)) +>a : Symbol(a, Decl(functionOverloads44.ts, 12, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads44.ts, 1, 36)) + + return undefined; +>undefined : Symbol(undefined) +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Symbol(x1, Decl(functionOverloads44.ts, 17, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>a : Symbol(a, Decl(functionOverloads44.ts, 17, 16)) + +var y1 = foo1([{a: 100}]); +>y1 : Symbol(y1, Decl(functionOverloads44.ts, 18, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads44.ts, 2, 36), Decl(functionOverloads44.ts, 4, 40), Decl(functionOverloads44.ts, 5, 43)) +>a : Symbol(a, Decl(functionOverloads44.ts, 18, 16)) + +var x2 = foo2([{a: "str"}]); +>x2 : Symbol(x2, Decl(functionOverloads44.ts, 20, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>a : Symbol(a, Decl(functionOverloads44.ts, 20, 16)) + +var y2 = foo2([{a: 100}]); +>y2 : Symbol(y2, Decl(functionOverloads44.ts, 21, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads44.ts, 8, 1), Decl(functionOverloads44.ts, 10, 40), Decl(functionOverloads44.ts, 11, 46)) +>a : Symbol(a, Decl(functionOverloads44.ts, 21, 16)) + diff --git a/tests/baselines/reference/functionOverloads44.types b/tests/baselines/reference/functionOverloads44.types new file mode 100644 index 00000000000..56cad09b472 --- /dev/null +++ b/tests/baselines/reference/functionOverloads44.types @@ -0,0 +1,97 @@ +=== tests/cases/compiler/functionOverloads44.ts === +interface Animal { animal } +>Animal : Animal +>animal : any + +interface Dog extends Animal { dog } +>Dog : Dog +>Animal : Animal +>dog : any + +interface Cat extends Animal { cat } +>Cat : Cat +>Animal : Animal +>cat : any + +function foo1(bar: { a:number }[]): Dog; +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>bar : { a: number; }[] +>a : number +>Dog : Dog + +function foo1(bar: { a:string }[]): Animal; +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>bar : { a: string; }[] +>a : string +>Animal : Animal + +function foo1([x]: { a:number | string }[]): Dog { +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>x : { a: number | string; } +>a : number | string +>Dog : Dog + + return undefined; +>undefined : undefined +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo2(bar: { a:string }[]): Cat | Dog; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>bar : { a: string; }[] +>a : string +>Cat : Cat +>Dog : Dog + +function foo2([x]: { a:number | string }[]): Cat { +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>x : { a: number | string; } +>a : number | string +>Cat : Cat + + return undefined; +>undefined : undefined +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Animal +>foo1([{a: "str"}]) : Animal +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y1 = foo1([{a: 100}]); +>y1 : Dog +>foo1([{a: 100}]) : Dog +>foo1 : { (bar: { a: number; }[]): Dog; (bar: { a: string; }[]): Animal; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + +var x2 = foo2([{a: "str"}]); +>x2 : Cat | Dog +>foo2([{a: "str"}]) : Cat | Dog +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y2 = foo2([{a: 100}]); +>y2 : Cat +>foo2([{a: 100}]) : Cat +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Cat | Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/functionOverloads45.errors.txt b/tests/baselines/reference/functionOverloads45.errors.txt new file mode 100644 index 00000000000..38ed387d9a1 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.errors.txt @@ -0,0 +1,31 @@ +tests/cases/compiler/functionOverloads45.ts(5,10): error TS2394: Overload signature is not compatible with function implementation. +tests/cases/compiler/functionOverloads45.ts(11,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/compiler/functionOverloads45.ts (2 errors) ==== + interface Animal { animal } + interface Dog extends Animal { dog } + interface Cat extends Animal { cat } + + function foo1(bar: { a:number }[]): Cat; + ~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo1(bar: { a:string }[]): Dog; + function foo1([x]: { a:number | string }[]): Animal { + return undefined; + } + + function foo2(bar: { a:number }[]): Cat; + ~~~~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function foo2(bar: { a:string }[]): Dog; + function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; + } + + + var x1 = foo1([{a: "str"}]); + var y1 = foo1([{a: 100}]); + + var x2 = foo2([{a: "str"}]); + var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads45.js b/tests/baselines/reference/functionOverloads45.js new file mode 100644 index 00000000000..89bf41893c9 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.js @@ -0,0 +1,37 @@ +//// [functionOverloads45.ts] +interface Animal { animal } +interface Dog extends Animal { dog } +interface Cat extends Animal { cat } + +function foo1(bar: { a:number }[]): Cat; +function foo1(bar: { a:string }[]): Dog; +function foo1([x]: { a:number | string }[]): Animal { + return undefined; +} + +function foo2(bar: { a:number }[]): Cat; +function foo2(bar: { a:string }[]): Dog; +function foo2([x]: { a:number | string }[]): Cat | Dog { + return undefined; +} + + +var x1 = foo1([{a: "str"}]); +var y1 = foo1([{a: 100}]); + +var x2 = foo2([{a: "str"}]); +var y2 = foo2([{a: 100}]); + +//// [functionOverloads45.js] +function foo1(_a) { + var x = _a[0]; + return undefined; +} +function foo2(_a) { + var x = _a[0]; + return undefined; +} +var x1 = foo1([{ a: "str" }]); +var y1 = foo1([{ a: 100 }]); +var x2 = foo2([{ a: "str" }]); +var y2 = foo2([{ a: 100 }]); From dc2af2fb7fd1ca54e05c8cc211d05041b23dc708 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:08:23 -0800 Subject: [PATCH 16/75] Use different relation for overload compatibility. --- src/compiler/checker.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 30d4818592b..212d863e575 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4959,6 +4959,25 @@ namespace ts { return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined); } + function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean { + const erasedSource = getErasedSignature(implementation); + const erasedTarget = getErasedSignature(overload); + + const sourceReturnType = getReturnTypeOfSignature(erasedSource); + const targetReturnType = getReturnTypeOfSignature(erasedTarget); + if (checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) + || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { + const anyReturningSource = cloneSignature(erasedSource); + const anyReturningTarget = cloneSignature(erasedTarget); + anyReturningSource.resolvedReturnType = anyType; + anyReturningTarget.resolvedReturnType = anyType; + + const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); + const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); + return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); + } + } + /** * Checks if 'source' is related to 'target' (e.g.: is a assignable to). * @param source The left-hand-side of the relation. @@ -11683,7 +11702,7 @@ namespace ts { // // The implementation is completely unrelated to the specialized signature, yet we do not check this. for (const signature of signatures) { - if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) { + if (!signature.hasStringLiterals && !isImplementationCompatibleWithOverload(bodySignature, signature)) { error(signature.declaration, Diagnostics.Overload_signature_is_not_compatible_with_function_implementation); break; } From e1004fac60608142dff3941ef0ac586c71942fc8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:13:16 -0800 Subject: [PATCH 17/75] Removed misleading comment from test. --- tests/cases/compiler/overloadOnConstConstraintChecks4.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/compiler/overloadOnConstConstraintChecks4.ts b/tests/cases/compiler/overloadOnConstConstraintChecks4.ts index f63c5b46349..55425f63393 100644 --- a/tests/cases/compiler/overloadOnConstConstraintChecks4.ts +++ b/tests/cases/compiler/overloadOnConstConstraintChecks4.ts @@ -6,7 +6,7 @@ class C extends A { } function foo(name: 'hi'): B; function foo(name: 'bye'): C; -function foo(name: string): A; // error +function foo(name: string): A; function foo(name: any): Z { return null; } From 51d240989aada5f805808c4a1025f13ecbfba68f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 8 Dec 2015 17:13:46 -0800 Subject: [PATCH 18/75] Accepted baselines. --- .../reference/functionOverloads22.errors.txt | 10 - .../reference/functionOverloads22.symbols | 19 ++ .../reference/functionOverloads22.types | 22 +++ .../reference/functionOverloads43.errors.txt | 18 -- .../reference/functionOverloads43.symbols | 39 ++++ .../reference/functionOverloads43.types | 47 +++++ .../reference/functionOverloads45.errors.txt | 31 ---- .../reference/functionOverloads45.symbols | 81 ++++++++ .../reference/functionOverloads45.types | 97 ++++++++++ ...verloadOnConstConstraintChecks4.errors.txt | 19 -- .../overloadOnConstConstraintChecks4.js | 2 +- .../overloadOnConstConstraintChecks4.symbols | 43 +++++ .../overloadOnConstConstraintChecks4.types | 45 +++++ .../stringLiteralTypesOverloads01.errors.txt | 59 ------ .../stringLiteralTypesOverloads01.symbols | 144 +++++++++++++++ .../stringLiteralTypesOverloads01.types | 174 ++++++++++++++++++ 16 files changed, 712 insertions(+), 138 deletions(-) delete mode 100644 tests/baselines/reference/functionOverloads22.errors.txt create mode 100644 tests/baselines/reference/functionOverloads22.symbols create mode 100644 tests/baselines/reference/functionOverloads22.types delete mode 100644 tests/baselines/reference/functionOverloads43.errors.txt create mode 100644 tests/baselines/reference/functionOverloads43.symbols create mode 100644 tests/baselines/reference/functionOverloads43.types delete mode 100644 tests/baselines/reference/functionOverloads45.errors.txt create mode 100644 tests/baselines/reference/functionOverloads45.symbols create mode 100644 tests/baselines/reference/functionOverloads45.types delete mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt create mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.symbols create mode 100644 tests/baselines/reference/overloadOnConstConstraintChecks4.types delete mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesOverloads01.types diff --git a/tests/baselines/reference/functionOverloads22.errors.txt b/tests/baselines/reference/functionOverloads22.errors.txt deleted file mode 100644 index c9fc8aa2b2f..00000000000 --- a/tests/baselines/reference/functionOverloads22.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/compiler/functionOverloads22.ts(2,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads22.ts (1 errors) ==== - function foo(bar:number):{a:number;}[]; - function foo(bar:string):{a:number; b:string;}[]; - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } - \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads22.symbols b/tests/baselines/reference/functionOverloads22.symbols new file mode 100644 index 00000000000..7924da073b0 --- /dev/null +++ b/tests/baselines/reference/functionOverloads22.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/functionOverloads22.ts === +function foo(bar:number):{a:number;}[]; +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 0, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 0, 26)) + +function foo(bar:string):{a:number; b:string;}[]; +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 1, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 1, 26)) +>b : Symbol(b, Decl(functionOverloads22.ts, 1, 35)) + +function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } +>foo : Symbol(foo, Decl(functionOverloads22.ts, 0, 0), Decl(functionOverloads22.ts, 0, 39), Decl(functionOverloads22.ts, 1, 49)) +>bar : Symbol(bar, Decl(functionOverloads22.ts, 2, 13)) +>a : Symbol(a, Decl(functionOverloads22.ts, 2, 23)) +>b : Symbol(b, Decl(functionOverloads22.ts, 2, 29)) +>a : Symbol(a, Decl(functionOverloads22.ts, 2, 51)) + diff --git a/tests/baselines/reference/functionOverloads22.types b/tests/baselines/reference/functionOverloads22.types new file mode 100644 index 00000000000..7557b1c049f --- /dev/null +++ b/tests/baselines/reference/functionOverloads22.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/functionOverloads22.ts === +function foo(bar:number):{a:number;}[]; +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : number +>a : number + +function foo(bar:string):{a:number; b:string;}[]; +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : string +>a : number +>b : string + +function foo(bar:any):{a:any;b?:any;}[] { return [{a:""}] } +>foo : { (bar: number): { a: number; }[]; (bar: string): { a: number; b: string; }[]; } +>bar : any +>a : any +>b : any +>[{a:""}] : { a: string; }[] +>{a:""} : { a: string; } +>a : string +>"" : string + diff --git a/tests/baselines/reference/functionOverloads43.errors.txt b/tests/baselines/reference/functionOverloads43.errors.txt deleted file mode 100644 index 769bb467186..00000000000 --- a/tests/baselines/reference/functionOverloads43.errors.txt +++ /dev/null @@ -1,18 +0,0 @@ -tests/cases/compiler/functionOverloads43.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads43.ts (1 errors) ==== - function foo(bar: { a:number }[]): number; - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(bar: { a:string }[]): string; - function foo([x]: { a:number | string }[]): string | number { - if (x) { - return x.a; - } - - return undefined; - } - - var x = foo([{a: "str"}]); - var y = foo([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads43.symbols b/tests/baselines/reference/functionOverloads43.symbols new file mode 100644 index 00000000000..179ba3e3fed --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.symbols @@ -0,0 +1,39 @@ +=== tests/cases/compiler/functionOverloads43.ts === +function foo(bar: { a:number }[]): number; +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>bar : Symbol(bar, Decl(functionOverloads43.ts, 0, 13)) +>a : Symbol(a, Decl(functionOverloads43.ts, 0, 19)) + +function foo(bar: { a:string }[]): string; +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>bar : Symbol(bar, Decl(functionOverloads43.ts, 1, 13)) +>a : Symbol(a, Decl(functionOverloads43.ts, 1, 19)) + +function foo([x]: { a:number | string }[]): string | number { +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) +>a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) + + if (x) { +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) + + return x.a; +>x.a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) +>x : Symbol(x, Decl(functionOverloads43.ts, 2, 14)) +>a : Symbol(a, Decl(functionOverloads43.ts, 2, 19)) + } + + return undefined; +>undefined : Symbol(undefined) +} + +var x = foo([{a: "str"}]); +>x : Symbol(x, Decl(functionOverloads43.ts, 10, 3)) +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>a : Symbol(a, Decl(functionOverloads43.ts, 10, 14)) + +var y = foo([{a: 100}]); +>y : Symbol(y, Decl(functionOverloads43.ts, 11, 3)) +>foo : Symbol(foo, Decl(functionOverloads43.ts, 0, 0), Decl(functionOverloads43.ts, 0, 42), Decl(functionOverloads43.ts, 1, 42)) +>a : Symbol(a, Decl(functionOverloads43.ts, 11, 14)) + diff --git a/tests/baselines/reference/functionOverloads43.types b/tests/baselines/reference/functionOverloads43.types new file mode 100644 index 00000000000..7c0fa8eb818 --- /dev/null +++ b/tests/baselines/reference/functionOverloads43.types @@ -0,0 +1,47 @@ +=== tests/cases/compiler/functionOverloads43.ts === +function foo(bar: { a:number }[]): number; +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>bar : { a: number; }[] +>a : number + +function foo(bar: { a:string }[]): string; +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>bar : { a: string; }[] +>a : string + +function foo([x]: { a:number | string }[]): string | number { +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>x : { a: number | string; } +>a : number | string + + if (x) { +>x : { a: number | string; } + + return x.a; +>x.a : number | string +>x : { a: number | string; } +>a : number | string + } + + return undefined; +>undefined : undefined +} + +var x = foo([{a: "str"}]); +>x : string +>foo([{a: "str"}]) : string +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y = foo([{a: 100}]); +>y : number +>foo([{a: 100}]) : number +>foo : { (bar: { a: number; }[]): number; (bar: { a: string; }[]): string; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/functionOverloads45.errors.txt b/tests/baselines/reference/functionOverloads45.errors.txt deleted file mode 100644 index 38ed387d9a1..00000000000 --- a/tests/baselines/reference/functionOverloads45.errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -tests/cases/compiler/functionOverloads45.ts(5,10): error TS2394: Overload signature is not compatible with function implementation. -tests/cases/compiler/functionOverloads45.ts(11,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/functionOverloads45.ts (2 errors) ==== - interface Animal { animal } - interface Dog extends Animal { dog } - interface Cat extends Animal { cat } - - function foo1(bar: { a:number }[]): Cat; - ~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo1(bar: { a:string }[]): Dog; - function foo1([x]: { a:number | string }[]): Animal { - return undefined; - } - - function foo2(bar: { a:number }[]): Cat; - ~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo2(bar: { a:string }[]): Dog; - function foo2([x]: { a:number | string }[]): Cat | Dog { - return undefined; - } - - - var x1 = foo1([{a: "str"}]); - var y1 = foo1([{a: 100}]); - - var x2 = foo2([{a: "str"}]); - var y2 = foo2([{a: 100}]); \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloads45.symbols b/tests/baselines/reference/functionOverloads45.symbols new file mode 100644 index 00000000000..28599339099 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.symbols @@ -0,0 +1,81 @@ +=== tests/cases/compiler/functionOverloads45.ts === +interface Animal { animal } +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>animal : Symbol(animal, Decl(functionOverloads45.ts, 0, 18)) + +interface Dog extends Animal { dog } +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>dog : Symbol(dog, Decl(functionOverloads45.ts, 1, 30)) + +interface Cat extends Animal { cat } +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) +>cat : Symbol(cat, Decl(functionOverloads45.ts, 2, 30)) + +function foo1(bar: { a:number }[]): Cat; +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 4, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 4, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) + +function foo1(bar: { a:string }[]): Dog; +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 5, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 5, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + +function foo1([x]: { a:number | string }[]): Animal { +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>x : Symbol(x, Decl(functionOverloads45.ts, 6, 15)) +>a : Symbol(a, Decl(functionOverloads45.ts, 6, 20)) +>Animal : Symbol(Animal, Decl(functionOverloads45.ts, 0, 0)) + + return undefined; +>undefined : Symbol(undefined) +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 10, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 10, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) + +function foo2(bar: { a:string }[]): Dog; +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>bar : Symbol(bar, Decl(functionOverloads45.ts, 11, 14)) +>a : Symbol(a, Decl(functionOverloads45.ts, 11, 20)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + +function foo2([x]: { a:number | string }[]): Cat | Dog { +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>x : Symbol(x, Decl(functionOverloads45.ts, 12, 15)) +>a : Symbol(a, Decl(functionOverloads45.ts, 12, 20)) +>Cat : Symbol(Cat, Decl(functionOverloads45.ts, 1, 36)) +>Dog : Symbol(Dog, Decl(functionOverloads45.ts, 0, 27)) + + return undefined; +>undefined : Symbol(undefined) +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Symbol(x1, Decl(functionOverloads45.ts, 17, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 17, 16)) + +var y1 = foo1([{a: 100}]); +>y1 : Symbol(y1, Decl(functionOverloads45.ts, 18, 3)) +>foo1 : Symbol(foo1, Decl(functionOverloads45.ts, 2, 36), Decl(functionOverloads45.ts, 4, 40), Decl(functionOverloads45.ts, 5, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 18, 16)) + +var x2 = foo2([{a: "str"}]); +>x2 : Symbol(x2, Decl(functionOverloads45.ts, 20, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 20, 16)) + +var y2 = foo2([{a: 100}]); +>y2 : Symbol(y2, Decl(functionOverloads45.ts, 21, 3)) +>foo2 : Symbol(foo2, Decl(functionOverloads45.ts, 8, 1), Decl(functionOverloads45.ts, 10, 40), Decl(functionOverloads45.ts, 11, 40)) +>a : Symbol(a, Decl(functionOverloads45.ts, 21, 16)) + diff --git a/tests/baselines/reference/functionOverloads45.types b/tests/baselines/reference/functionOverloads45.types new file mode 100644 index 00000000000..257a615e334 --- /dev/null +++ b/tests/baselines/reference/functionOverloads45.types @@ -0,0 +1,97 @@ +=== tests/cases/compiler/functionOverloads45.ts === +interface Animal { animal } +>Animal : Animal +>animal : any + +interface Dog extends Animal { dog } +>Dog : Dog +>Animal : Animal +>dog : any + +interface Cat extends Animal { cat } +>Cat : Cat +>Animal : Animal +>cat : any + +function foo1(bar: { a:number }[]): Cat; +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo1(bar: { a:string }[]): Dog; +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: string; }[] +>a : string +>Dog : Dog + +function foo1([x]: { a:number | string }[]): Animal { +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>x : { a: number | string; } +>a : number | string +>Animal : Animal + + return undefined; +>undefined : undefined +} + +function foo2(bar: { a:number }[]): Cat; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: number; }[] +>a : number +>Cat : Cat + +function foo2(bar: { a:string }[]): Dog; +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>bar : { a: string; }[] +>a : string +>Dog : Dog + +function foo2([x]: { a:number | string }[]): Cat | Dog { +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>x : { a: number | string; } +>a : number | string +>Cat : Cat +>Dog : Dog + + return undefined; +>undefined : undefined +} + + +var x1 = foo1([{a: "str"}]); +>x1 : Dog +>foo1([{a: "str"}]) : Dog +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y1 = foo1([{a: 100}]); +>y1 : Cat +>foo1([{a: 100}]) : Cat +>foo1 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + +var x2 = foo2([{a: "str"}]); +>x2 : Dog +>foo2([{a: "str"}]) : Dog +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: "str"}] : { a: string; }[] +>{a: "str"} : { a: string; } +>a : string +>"str" : string + +var y2 = foo2([{a: 100}]); +>y2 : Cat +>foo2([{a: 100}]) : Cat +>foo2 : { (bar: { a: number; }[]): Cat; (bar: { a: string; }[]): Dog; } +>[{a: 100}] : { a: number; }[] +>{a: 100} : { a: number; } +>a : number +>100 : number + diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt b/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt deleted file mode 100644 index 7a8037b3dd7..00000000000 --- a/tests/baselines/reference/overloadOnConstConstraintChecks4.errors.txt +++ /dev/null @@ -1,19 +0,0 @@ -tests/cases/compiler/overloadOnConstConstraintChecks4.ts(9,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/compiler/overloadOnConstConstraintChecks4.ts (1 errors) ==== - class Z { } - class A extends Z { private x = 1 } - class B extends A {} - class C extends A { - public foo() { } - } - function foo(name: 'hi'): B; - function foo(name: 'bye'): C; - function foo(name: string): A; // error - ~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function foo(name: any): Z { - return null; - } - \ No newline at end of file diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.js b/tests/baselines/reference/overloadOnConstConstraintChecks4.js index 17ec3779620..c0422e3611e 100644 --- a/tests/baselines/reference/overloadOnConstConstraintChecks4.js +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.js @@ -7,7 +7,7 @@ class C extends A { } function foo(name: 'hi'): B; function foo(name: 'bye'): C; -function foo(name: string): A; // error +function foo(name: string): A; function foo(name: any): Z { return null; } diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols b/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols new file mode 100644 index 00000000000..6e2a34b55e9 --- /dev/null +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/overloadOnConstConstraintChecks4.ts === +class Z { } +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) + +class A extends Z { private x = 1 } +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) +>x : Symbol(x, Decl(overloadOnConstConstraintChecks4.ts, 1, 19)) + +class B extends A {} +>B : Symbol(B, Decl(overloadOnConstConstraintChecks4.ts, 1, 35)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + +class C extends A { +>C : Symbol(C, Decl(overloadOnConstConstraintChecks4.ts, 2, 20)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + + public foo() { } +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 3, 19)) +} +function foo(name: 'hi'): B; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 6, 13)) +>B : Symbol(B, Decl(overloadOnConstConstraintChecks4.ts, 1, 35)) + +function foo(name: 'bye'): C; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 7, 13)) +>C : Symbol(C, Decl(overloadOnConstConstraintChecks4.ts, 2, 20)) + +function foo(name: string): A; +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 8, 13)) +>A : Symbol(A, Decl(overloadOnConstConstraintChecks4.ts, 0, 11)) + +function foo(name: any): Z { +>foo : Symbol(foo, Decl(overloadOnConstConstraintChecks4.ts, 5, 1), Decl(overloadOnConstConstraintChecks4.ts, 6, 28), Decl(overloadOnConstConstraintChecks4.ts, 7, 29), Decl(overloadOnConstConstraintChecks4.ts, 8, 30)) +>name : Symbol(name, Decl(overloadOnConstConstraintChecks4.ts, 9, 13)) +>Z : Symbol(Z, Decl(overloadOnConstConstraintChecks4.ts, 0, 0)) + + return null; +} + diff --git a/tests/baselines/reference/overloadOnConstConstraintChecks4.types b/tests/baselines/reference/overloadOnConstConstraintChecks4.types new file mode 100644 index 00000000000..6ca7288ead9 --- /dev/null +++ b/tests/baselines/reference/overloadOnConstConstraintChecks4.types @@ -0,0 +1,45 @@ +=== tests/cases/compiler/overloadOnConstConstraintChecks4.ts === +class Z { } +>Z : Z + +class A extends Z { private x = 1 } +>A : A +>Z : Z +>x : number +>1 : number + +class B extends A {} +>B : B +>A : A + +class C extends A { +>C : C +>A : A + + public foo() { } +>foo : () => void +} +function foo(name: 'hi'): B; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : "hi" +>B : B + +function foo(name: 'bye'): C; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : "bye" +>C : C + +function foo(name: string): A; +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : string +>A : A + +function foo(name: any): Z { +>foo : { (name: "hi"): B; (name: "bye"): C; (name: string): A; } +>name : any +>Z : Z + + return null; +>null : null +} + diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt b/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt deleted file mode 100644 index 0a3fdb91929..00000000000 --- a/tests/baselines/reference/stringLiteralTypesOverloads01.errors.txt +++ /dev/null @@ -1,59 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts(7,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts (1 errors) ==== - - type PrimitiveName = 'string' | 'number' | 'boolean'; - - function getFalsyPrimitive(x: "string"): string; - function getFalsyPrimitive(x: "number"): number; - function getFalsyPrimitive(x: "boolean"): boolean; - function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; - ~~~~~~~~~~~~~~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; - function getFalsyPrimitive(x: "number" | "string"): number | string; - function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; - function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { - if (x === "string") { - return ""; - } - if (x === "number") { - return 0; - } - if (x === "boolean") { - return false; - } - - // Should be unreachable. - throw "Invalid value"; - } - - namespace Consts1 { - const EMPTY_STRING = getFalsyPrimitive("string"); - const ZERO = getFalsyPrimitive('number'); - const FALSE = getFalsyPrimitive("boolean"); - } - - const string: "string" = "string" - const number: "number" = "number" - const boolean: "boolean" = "boolean" - - const stringOrNumber = string || number; - const stringOrBoolean = string || boolean; - const booleanOrNumber = number || boolean; - const stringOrBooleanOrNumber = stringOrBoolean || number; - - namespace Consts2 { - const EMPTY_STRING = getFalsyPrimitive(string); - const ZERO = getFalsyPrimitive(number); - const FALSE = getFalsyPrimitive(boolean); - - const a = getFalsyPrimitive(stringOrNumber); - const b = getFalsyPrimitive(stringOrBoolean); - const c = getFalsyPrimitive(booleanOrNumber); - const d = getFalsyPrimitive(stringOrBooleanOrNumber); - } - - - \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.symbols b/tests/baselines/reference/stringLiteralTypesOverloads01.symbols new file mode 100644 index 00000000000..c92fe134076 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.symbols @@ -0,0 +1,144 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts === + +type PrimitiveName = 'string' | 'number' | 'boolean'; +>PrimitiveName : Symbol(PrimitiveName, Decl(stringLiteralTypesOverloads01.ts, 0, 0)) + +function getFalsyPrimitive(x: "string"): string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 3, 27)) + +function getFalsyPrimitive(x: "number"): number; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 4, 27)) + +function getFalsyPrimitive(x: "boolean"): boolean; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 5, 27)) + +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 6, 27)) + +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 7, 27)) + +function getFalsyPrimitive(x: "number" | "string"): number | string; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 8, 27)) + +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 9, 27)) + +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) +>PrimitiveName : Symbol(PrimitiveName, Decl(stringLiteralTypesOverloads01.ts, 0, 0)) + + if (x === "string") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return ""; + } + if (x === "number") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return 0; + } + if (x === "boolean") { +>x : Symbol(x, Decl(stringLiteralTypesOverloads01.ts, 10, 27)) + + return false; + } + + // Should be unreachable. + throw "Invalid value"; +} + +namespace Consts1 { +>Consts1 : Symbol(Consts1, Decl(stringLiteralTypesOverloads01.ts, 23, 1)) + + const EMPTY_STRING = getFalsyPrimitive("string"); +>EMPTY_STRING : Symbol(EMPTY_STRING, Decl(stringLiteralTypesOverloads01.ts, 26, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) + + const ZERO = getFalsyPrimitive('number'); +>ZERO : Symbol(ZERO, Decl(stringLiteralTypesOverloads01.ts, 27, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) + + const FALSE = getFalsyPrimitive("boolean"); +>FALSE : Symbol(FALSE, Decl(stringLiteralTypesOverloads01.ts, 28, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +} + +const string: "string" = "string" +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) + +const number: "number" = "number" +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +const boolean: "boolean" = "boolean" +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const stringOrNumber = string || number; +>stringOrNumber : Symbol(stringOrNumber, Decl(stringLiteralTypesOverloads01.ts, 35, 5)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +const stringOrBoolean = string || boolean; +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const booleanOrNumber = number || boolean; +>booleanOrNumber : Symbol(booleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 37, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + +const stringOrBooleanOrNumber = stringOrBoolean || number; +>stringOrBooleanOrNumber : Symbol(stringOrBooleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 38, 5)) +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + +namespace Consts2 { +>Consts2 : Symbol(Consts2, Decl(stringLiteralTypesOverloads01.ts, 38, 58)) + + const EMPTY_STRING = getFalsyPrimitive(string); +>EMPTY_STRING : Symbol(EMPTY_STRING, Decl(stringLiteralTypesOverloads01.ts, 41, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>string : Symbol(string, Decl(stringLiteralTypesOverloads01.ts, 31, 5)) + + const ZERO = getFalsyPrimitive(number); +>ZERO : Symbol(ZERO, Decl(stringLiteralTypesOverloads01.ts, 42, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>number : Symbol(number, Decl(stringLiteralTypesOverloads01.ts, 32, 5)) + + const FALSE = getFalsyPrimitive(boolean); +>FALSE : Symbol(FALSE, Decl(stringLiteralTypesOverloads01.ts, 43, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>boolean : Symbol(boolean, Decl(stringLiteralTypesOverloads01.ts, 33, 5)) + + const a = getFalsyPrimitive(stringOrNumber); +>a : Symbol(a, Decl(stringLiteralTypesOverloads01.ts, 45, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrNumber : Symbol(stringOrNumber, Decl(stringLiteralTypesOverloads01.ts, 35, 5)) + + const b = getFalsyPrimitive(stringOrBoolean); +>b : Symbol(b, Decl(stringLiteralTypesOverloads01.ts, 46, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrBoolean : Symbol(stringOrBoolean, Decl(stringLiteralTypesOverloads01.ts, 36, 5)) + + const c = getFalsyPrimitive(booleanOrNumber); +>c : Symbol(c, Decl(stringLiteralTypesOverloads01.ts, 47, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>booleanOrNumber : Symbol(booleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 37, 5)) + + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +>d : Symbol(d, Decl(stringLiteralTypesOverloads01.ts, 48, 9)) +>getFalsyPrimitive : Symbol(getFalsyPrimitive, Decl(stringLiteralTypesOverloads01.ts, 1, 53), Decl(stringLiteralTypesOverloads01.ts, 3, 48), Decl(stringLiteralTypesOverloads01.ts, 4, 48), Decl(stringLiteralTypesOverloads01.ts, 5, 50), Decl(stringLiteralTypesOverloads01.ts, 6, 70), Decl(stringLiteralTypesOverloads01.ts, 7, 70), Decl(stringLiteralTypesOverloads01.ts, 8, 68), Decl(stringLiteralTypesOverloads01.ts, 9, 90)) +>stringOrBooleanOrNumber : Symbol(stringOrBooleanOrNumber, Decl(stringLiteralTypesOverloads01.ts, 38, 5)) +} + + + diff --git a/tests/baselines/reference/stringLiteralTypesOverloads01.types b/tests/baselines/reference/stringLiteralTypesOverloads01.types new file mode 100644 index 00000000000..6ba8d482117 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesOverloads01.types @@ -0,0 +1,174 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts === + +type PrimitiveName = 'string' | 'number' | 'boolean'; +>PrimitiveName : "string" | "number" | "boolean" + +function getFalsyPrimitive(x: "string"): string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "string" + +function getFalsyPrimitive(x: "number"): number; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" + +function getFalsyPrimitive(x: "boolean"): boolean; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" + +function getFalsyPrimitive(x: "boolean" | "string"): boolean | string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" | "string" + +function getFalsyPrimitive(x: "boolean" | "number"): boolean | number; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "boolean" | "number" + +function getFalsyPrimitive(x: "number" | "string"): number | string; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" | "string" + +function getFalsyPrimitive(x: "number" | "string" | "boolean"): number | string | boolean; +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "number" | "string" | "boolean" + +function getFalsyPrimitive(x: PrimitiveName): number | string | boolean { +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>x : "string" | "number" | "boolean" +>PrimitiveName : "string" | "number" | "boolean" + + if (x === "string") { +>x === "string" : boolean +>x : "string" | "number" | "boolean" +>"string" : string + + return ""; +>"" : string + } + if (x === "number") { +>x === "number" : boolean +>x : "string" | "number" | "boolean" +>"number" : string + + return 0; +>0 : number + } + if (x === "boolean") { +>x === "boolean" : boolean +>x : "string" | "number" | "boolean" +>"boolean" : string + + return false; +>false : boolean + } + + // Should be unreachable. + throw "Invalid value"; +>"Invalid value" : string +} + +namespace Consts1 { +>Consts1 : typeof Consts1 + + const EMPTY_STRING = getFalsyPrimitive("string"); +>EMPTY_STRING : string +>getFalsyPrimitive("string") : string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>"string" : "string" + + const ZERO = getFalsyPrimitive('number'); +>ZERO : number +>getFalsyPrimitive('number') : number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>'number' : "number" + + const FALSE = getFalsyPrimitive("boolean"); +>FALSE : boolean +>getFalsyPrimitive("boolean") : boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>"boolean" : "boolean" +} + +const string: "string" = "string" +>string : "string" +>"string" : "string" + +const number: "number" = "number" +>number : "number" +>"number" : "number" + +const boolean: "boolean" = "boolean" +>boolean : "boolean" +>"boolean" : "boolean" + +const stringOrNumber = string || number; +>stringOrNumber : "string" | "number" +>string || number : "string" | "number" +>string : "string" +>number : "number" + +const stringOrBoolean = string || boolean; +>stringOrBoolean : "string" | "boolean" +>string || boolean : "string" | "boolean" +>string : "string" +>boolean : "boolean" + +const booleanOrNumber = number || boolean; +>booleanOrNumber : "number" | "boolean" +>number || boolean : "number" | "boolean" +>number : "number" +>boolean : "boolean" + +const stringOrBooleanOrNumber = stringOrBoolean || number; +>stringOrBooleanOrNumber : "string" | "boolean" | "number" +>stringOrBoolean || number : "string" | "boolean" | "number" +>stringOrBoolean : "string" | "boolean" +>number : "number" + +namespace Consts2 { +>Consts2 : typeof Consts2 + + const EMPTY_STRING = getFalsyPrimitive(string); +>EMPTY_STRING : string +>getFalsyPrimitive(string) : string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>string : "string" + + const ZERO = getFalsyPrimitive(number); +>ZERO : number +>getFalsyPrimitive(number) : number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>number : "number" + + const FALSE = getFalsyPrimitive(boolean); +>FALSE : boolean +>getFalsyPrimitive(boolean) : boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>boolean : "boolean" + + const a = getFalsyPrimitive(stringOrNumber); +>a : number | string +>getFalsyPrimitive(stringOrNumber) : number | string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrNumber : "string" | "number" + + const b = getFalsyPrimitive(stringOrBoolean); +>b : boolean | string +>getFalsyPrimitive(stringOrBoolean) : boolean | string +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrBoolean : "string" | "boolean" + + const c = getFalsyPrimitive(booleanOrNumber); +>c : boolean | number +>getFalsyPrimitive(booleanOrNumber) : boolean | number +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>booleanOrNumber : "number" | "boolean" + + const d = getFalsyPrimitive(stringOrBooleanOrNumber); +>d : number | string | boolean +>getFalsyPrimitive(stringOrBooleanOrNumber) : number | string | boolean +>getFalsyPrimitive : { (x: "string"): string; (x: "number"): number; (x: "boolean"): boolean; (x: "boolean" | "string"): boolean | string; (x: "boolean" | "number"): boolean | number; (x: "number" | "string"): number | string; (x: "number" | "string" | "boolean"): number | string | boolean; } +>stringOrBooleanOrNumber : "string" | "boolean" | "number" +} + + + From 50892acfd855b0a0ae42a4e2f2186fd11948753f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 9 Dec 2015 11:16:57 -0800 Subject: [PATCH 19/75] Address CR feedback --- src/compiler/checker.ts | 17 ++++++++++------- src/compiler/types.ts | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 79f514e7864..5e8fd45510e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2671,11 +2671,6 @@ namespace ts { // Handle exports.p = expr or this.p = expr or className.prototype.method = expr return links.type = checkExpressionCached((declaration.parent).right); } - else { - // Declaration for className.prototype in inferred JS class - const type = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, undefined, undefined); - return links.type = type; - } } // Handle variable, parameter or property if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { @@ -6908,7 +6903,7 @@ namespace ts { .expression as PropertyAccessExpression) // x.prototype .expression; // x const classSymbol = checkExpression(className).symbol; - if (classSymbol.members) { + if (classSymbol && classSymbol.members) { return createAnonymousType(undefined, classSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); } } @@ -9635,6 +9630,14 @@ namespace ts { return links.resolvedSignature; } + function getInferredClassType(symbol: Symbol) { + const links = getSymbolLinks(symbol); + if (!links.inferredClassType) { + links.inferredClassType = createAnonymousType(undefined, symbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + } + return links.inferredClassType; + } + /** * Syntactically and semantically checks a call or new expression. * @param node The call/new expression to be checked. @@ -9661,7 +9664,7 @@ namespace ts { // in a JS file const funcSymbol = checkExpression(node.expression).symbol; if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) { - return createAnonymousType(undefined, funcSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + return getInferredClassType(funcSymbol); } else if (compilerOptions.noImplicitAny) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 34e862768d0..2e557ad09a4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1997,6 +1997,7 @@ namespace ts { type?: Type; // Type of value symbol declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic) + inferredClassType?: Type; // Type of an inferred ES5 class instantiations?: Map; // Instantiations of generic type alias (undefined if non-generic) mapper?: TypeMapper; // Type mapper for instantiation alias referenced?: boolean; // True if alias symbol has been referenced as a value From fcfc424b491bc139a02a1e4b09c0fb92f932b631 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 9 Dec 2015 11:18:40 -0800 Subject: [PATCH 20/75] One more --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e8fd45510e..7e2bf85c59b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6904,7 +6904,7 @@ namespace ts { .expression; // x const classSymbol = checkExpression(className).symbol; if (classSymbol && classSymbol.members) { - return createAnonymousType(undefined, classSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + return getInferredClassType(classSymbol); } } } From 6cd5a4dac9599122eff78d016a82ac0d362850ab Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:03:45 -0800 Subject: [PATCH 21/75] Compare enums semi-structurally. 1. Unqualified names must match. 2. Target contains members with same names as all source members. --- src/compiler/checker.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50a3aee9955..0f04daf2983 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5040,6 +5040,11 @@ namespace ts { if (source === undefinedType) return Ternary.True; if (source === nullType && target !== undefinedType) return Ternary.True; if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True; + if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) { + if (result = enumRelatedTo(source, target)) { + return result; + } + } if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True; if (relation === assignableRelation) { if (isTypeAny(source)) return Ternary.True; @@ -5750,6 +5755,25 @@ namespace ts { } return Ternary.False; } + + function enumRelatedTo(source: Type, target: Type) { + if (source.symbol.name !== target.symbol.name) { + return Ternary.False; + } + const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; + const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); + for (const member of sourceDecl.members) { + const name = getTextOfPropertyName(member.name); + if (!targetMembers[name]) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } + } + return Ternary.True; + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From 6ed5b59f751f57532e43cbc0ac71ff097bcc899b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 11:05:25 -0800 Subject: [PATCH 22/75] Add test case and accept baseline --- .../enumAssignmentCompat3.errors.txt | 75 ++++++++++++ .../reference/enumAssignmentCompat3.js | 115 ++++++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 45 +++++++ 3 files changed, 235 insertions(+) create mode 100644 tests/baselines/reference/enumAssignmentCompat3.errors.txt create mode 100644 tests/baselines/reference/enumAssignmentCompat3.js create mode 100644 tests/cases/compiler/enumAssignmentCompat3.ts diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt new file mode 100644 index 00000000000..d82a4b7d490 --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -0,0 +1,75 @@ +tests/cases/compiler/enumAssignmentCompat3.ts(37,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(39,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(43,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. + Property 'c' is missing in type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(44,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. + Property 'a' is missing in type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. + + +==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== + namespace First { + export enum E { + a, b, c, + } + } + namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } + } + namespace Abcd { + export enum E { + a, b, c, d, + } + } + namespace Ab { + export enum E { + a, b, + } + } + namespace Cd { + export enum E { + c, d, + } + } + + var abc: First.E; + var secondAbc: Abc.E; + var secondAbcd: Abcd.E; + var secondAb: Ab.E; + var secondCd: Cd.E; + var nope: Abc.Nope; + abc = secondAbc; // ok + abc = secondAbcd; // missing 'd' + ~~~ +!!! error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + abc = secondAb; // ok + abc = secondCd; // missing 'd' + ~~~ +!!! error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + abc = nope; // nope! + ~~~ +!!! error TS2322: Type 'Nope' is not assignable to type 'E'. + secondAbc = abc; // ok + secondAbcd = abc; // ok + secondAb = abc; // missing 'c' + ~~~~~~~~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +!!! error TS2322: Property 'c' is missing in type 'Ab.E'. + secondCd = abc; // missing 'a' and 'b' + ~~~~~~~~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +!!! error TS2322: Property 'a' is missing in type 'Cd.E'. + nope = abc; // nope! + ~~~~ +!!! error TS2322: Type 'E' is not assignable to type 'Nope'. + \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js new file mode 100644 index 00000000000..33cfdd28e88 --- /dev/null +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -0,0 +1,115 @@ +//// [enumAssignmentCompat3.ts] +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! + + +//// [enumAssignmentCompat3.js] +var First; +(function (First) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(First.E || (First.E = {})); + var E = First.E; +})(First || (First = {})); +var Abc; +(function (Abc) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Abc.E || (Abc.E = {})); + var E = Abc.E; + (function (Nope) { + Nope[Nope["a"] = 0] = "a"; + Nope[Nope["b"] = 1] = "b"; + Nope[Nope["c"] = 2] = "c"; + })(Abc.Nope || (Abc.Nope = {})); + var Nope = Abc.Nope; +})(Abc || (Abc = {})); +var Abcd; +(function (Abcd) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + E[E["d"] = 3] = "d"; + })(Abcd.E || (Abcd.E = {})); + var E = Abcd.E; +})(Abcd || (Abcd = {})); +var Ab; +(function (Ab) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Ab.E || (Ab.E = {})); + var E = Ab.E; +})(Ab || (Ab = {})); +var Cd; +(function (Cd) { + (function (E) { + E[E["c"] = 0] = "c"; + E[E["d"] = 1] = "d"; + })(Cd.E || (Cd.E = {})); + var E = Cd.E; +})(Cd || (Cd = {})); +var abc; +var secondAbc; +var secondAbcd; +var secondAb; +var secondCd; +var nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts new file mode 100644 index 00000000000..94a22c7f346 --- /dev/null +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -0,0 +1,45 @@ +namespace First { + export enum E { + a, b, c, + } +} +namespace Abc { + export enum E { + a, b, c, + } + export enum Nope { + a, b, c, + } +} +namespace Abcd { + export enum E { + a, b, c, d, + } +} +namespace Ab { + export enum E { + a, b, + } +} +namespace Cd { + export enum E { + c, d, + } +} + +var abc: First.E; +var secondAbc: Abc.E; +var secondAbcd: Abcd.E; +var secondAb: Ab.E; +var secondCd: Cd.E; +var nope: Abc.Nope; +abc = secondAbc; // ok +abc = secondAbcd; // missing 'd' +abc = secondAb; // ok +abc = secondCd; // missing 'd' +abc = nope; // nope! +secondAbc = abc; // ok +secondAbcd = abc; // ok +secondAb = abc; // missing 'c' +secondCd = abc; // missing 'a' and 'b' +nope = abc; // nope! From cc1d8cf395eebdf5e1f6e2f9ddb90111fbad95b7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:18 -0800 Subject: [PATCH 23/75] Address review comments --- src/compiler/checker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0f04daf2983..857fa97ca06 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5757,15 +5757,17 @@ namespace ts { } function enumRelatedTo(source: Type, target: Type) { - if (source.symbol.name !== target.symbol.name) { + if (source.symbol.name !== target.symbol.name || + source.symbol.flags & SymbolFlags.ConstEnum || + target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getMergedSymbol(source.symbol).valueDeclaration; - const targetDecl = getMergedSymbol(target.symbol).valueDeclaration; + const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); + const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); for (const member of sourceDecl.members) { const name = getTextOfPropertyName(member.name); - if (!targetMembers[name]) { + if (!hasProperty(targetMembers, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); From ff0138878ddbe5823df3d37073e875758f23ec18 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 13:47:31 -0800 Subject: [PATCH 24/75] Add tests from review --- .../enumAssignmentCompat3.errors.txt | 38 +++++++++++++++---- .../reference/enumAssignmentCompat3.js | 28 ++++++++++++++ tests/cases/compiler/enumAssignmentCompat3.ts | 18 +++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index d82a4b7d490..b9ab92adec1 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,18 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(37,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(49,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(39,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(51,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(40,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(43,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(56,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(44,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(57,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -==== tests/cases/compiler/enumAssignmentCompat3.ts (6 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (8 errors) ==== namespace First { export enum E { a, b, c, @@ -39,6 +41,16 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n c, d, } } + namespace Const { + export const enum E { + a, b, c, + } + } + namespace Decl { + export declare enum E { + a, b, c = 3, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +58,8 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; + var k: Const.E; + var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -59,6 +73,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n abc = nope; // nope! ~~~ !!! error TS2322: Type 'Nope' is not assignable to type 'E'. + abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' @@ -72,4 +87,13 @@ tests/cases/compiler/enumAssignmentCompat3.ts(45,1): error TS2322: Type 'E' is n nope = abc; // nope! ~~~~ !!! error TS2322: Type 'E' is not assignable to type 'Nope'. + decl = abc; // ok + + k = k; // const is only assignable to itself + abc = k; // error + ~~~ +!!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. + k = abc; + ~ +!!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 33cfdd28e88..1173bfa1812 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -27,6 +27,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -34,16 +44,24 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; //// [enumAssignmentCompat3.js] @@ -97,19 +115,29 @@ var Cd; })(Cd.E || (Cd.E = {})); var E = Cd.E; })(Cd || (Cd = {})); +var Decl; +(function (Decl) { +})(Decl || (Decl = {})); var abc; var secondAbc; var secondAbcd; var secondAb; var secondCd; var nope; +var k; +var decl; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok +k = k; // const is only assignable to itself +abc = k; // error +k = abc; diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 94a22c7f346..aaaf96b69c8 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -26,6 +26,16 @@ namespace Cd { c, d, } } +namespace Const { + export const enum E { + a, b, c, + } +} +namespace Decl { + export declare enum E { + a, b, c = 3, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -33,13 +43,21 @@ var secondAbcd: Abcd.E; var secondAb: Ab.E; var secondCd: Cd.E; var nope: Abc.Nope; +var k: Const.E; +var decl: Decl.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok abc = secondCd; // missing 'd' abc = nope; // nope! +abc = decl; // ok secondAbc = abc; // ok secondAbcd = abc; // ok secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! +decl = abc; // ok + +k = k; // const is only assignable to itself +abc = k; // error +k = abc; From a995b23e4a00e252de81cdf0d1685700314eefa6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:29 -0800 Subject: [PATCH 25/75] Handle merged enums --- src/compiler/checker.ts | 23 ++++++++++++++++++----- src/compiler/utilities.ts | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 857fa97ca06..2fb0296c1c7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,12 +5762,11 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.EnumDeclaration); - const targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.EnumDeclaration); - const targetMembers = arrayToMap(targetDecl.members, member => getTextOfPropertyName(member.name)); - for (const member of sourceDecl.members) { + const targetMembers = getEnumMembers(target.symbol); + const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); + for (const member of getEnumMembers(source.symbol)) { const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetMembers, name)) { + if (!hasProperty(targetNames, name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); @@ -5778,6 +5777,20 @@ namespace ts { } } + function getEnumMembers(symbol: Symbol): EnumMember[] { + const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); + if (!declarations) { + return emptyArray; + } + const members: EnumMember[] = []; + for (const declaration of declarations) { + for (const member of (declaration).members) { + members.push(member); + } + } + return members; + } + // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 95bf4ff7fa3..24e2149ab3e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,6 +27,21 @@ namespace ts { return undefined; } + export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { + const declarations = symbol.declarations; + if (declarations) { + const declarationsOfKind: Declaration[] = []; + for (const declaration of declarations) { + if (declaration.kind === kind) { + declarationsOfKind.push(declaration); + } + } + return declarationsOfKind; + } + + return undefined; + } + export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 75304096959652551cdeed4140753f44940e45b6 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 14:28:46 -0800 Subject: [PATCH 26/75] Add merged enum test --- .../enumAssignmentCompat3.errors.txt | 40 ++++++++++++++----- .../reference/enumAssignmentCompat3.js | 37 +++++++++++++++-- tests/cases/compiler/enumAssignmentCompat3.ts | 16 +++++++- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index b9ab92adec1..c34ad434347 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,18 +1,20 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(49,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(51,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(60,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(52,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(56,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(65,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(57,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(66,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(62,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. + Property 'd' is missing in type 'First.E'. -==== tests/cases/compiler/enumAssignmentCompat3.ts (8 errors) ==== +==== tests/cases/compiler/enumAssignmentCompat3.ts (9 errors) ==== namespace First { export enum E { a, b, c, @@ -51,6 +53,14 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E a, b, c = 3, } } + namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } + } var abc: First.E; var secondAbc: Abc.E; @@ -60,6 +70,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; + var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -89,11 +100,18 @@ tests/cases/compiler/enumAssignmentCompat3.ts(63,1): error TS2322: Type 'First.E !!! error TS2322: Type 'E' is not assignable to type 'Nope'. decl = abc; // ok - k = k; // const is only assignable to itself + // const is only assignable to itself + k = k; abc = k; // error ~~~ !!! error TS2322: Type 'Const.E' is not assignable to type 'First.E'. k = abc; ~ !!! error TS2322: Type 'First.E' is not assignable to type 'Const.E'. - \ No newline at end of file + + // merged enums compare all their members + abc = merged; // missing 'd' + ~~~ +!!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +!!! error TS2322: Property 'd' is missing in type 'First.E'. + merged = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index 1173bfa1812..e43874911ce 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -37,6 +37,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -46,6 +54,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -59,10 +68,14 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; - + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -118,6 +131,19 @@ var Cd; var Decl; (function (Decl) { })(Decl || (Decl = {})); +var Merged; +(function (Merged) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; + (function (E) { + E[E["c"] = 3] = "c"; + E[E["d"] = 4] = "d"; + })(Merged.E || (Merged.E = {})); + var E = Merged.E; +})(Merged || (Merged = {})); var abc; var secondAbc; var secondAbcd; @@ -126,6 +152,7 @@ var secondCd; var nope; var k; var decl; +var merged; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -138,6 +165,10 @@ secondAb = abc; // missing 'c' secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index aaaf96b69c8..33070572661 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -36,6 +36,14 @@ namespace Decl { a, b, c = 3, } } +namespace Merged { + export enum E { + a, b, + } + export enum E { + c = 3, d, + } +} var abc: First.E; var secondAbc: Abc.E; @@ -45,6 +53,7 @@ var secondCd: Cd.E; var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; +var merged: Merged.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -58,6 +67,11 @@ secondCd = abc; // missing 'a' and 'b' nope = abc; // nope! decl = abc; // ok -k = k; // const is only assignable to itself +// const is only assignable to itself +k = k; abc = k; // error k = abc; + +// merged enums compare all their members +abc = merged; // missing 'd' +merged = abc; // ok \ No newline at end of file From da8e19e191ef508d18f400db62c9297e44002da7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 10 Dec 2015 15:25:01 -0800 Subject: [PATCH 27/75] Use typeof enum to resolve members. Use getTypeOfSymbol >> resolveStructuredTypeMembers >> properties instead of looking at declarations. --- src/compiler/checker.ts | 26 ++++++-------------------- src/compiler/utilities.ts | 15 --------------- 2 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2fb0296c1c7..bccbede909b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,13 +5762,13 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetMembers = getEnumMembers(target.symbol); - const targetNames = arrayToMap(targetMembers, member => getTextOfPropertyName(member.name)); - for (const member of getEnumMembers(source.symbol)) { - const name = getTextOfPropertyName(member.name); - if (!hasProperty(targetNames, name)) { + const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; + const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; + const targetNames = arrayToMap(targetMembers, member => member.name); + for (const member of sourceMembers) { + if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, - name, + member.name, typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); return Ternary.False; } @@ -5777,20 +5777,6 @@ namespace ts { } } - function getEnumMembers(symbol: Symbol): EnumMember[] { - const declarations = getDeclarationsOfKind(symbol, SyntaxKind.EnumDeclaration); - if (!declarations) { - return emptyArray; - } - const members: EnumMember[] = []; - for (const declaration of declarations) { - for (const member of (declaration).members) { - members.push(member); - } - } - return members; - } - // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case // when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible, // though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 24e2149ab3e..95bf4ff7fa3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -27,21 +27,6 @@ namespace ts { return undefined; } - export function getDeclarationsOfKind(symbol: Symbol, kind: SyntaxKind): Declaration[] { - const declarations = symbol.declarations; - if (declarations) { - const declarationsOfKind: Declaration[] = []; - for (const declaration of declarations) { - if (declaration.kind === kind) { - declarationsOfKind.push(declaration); - } - } - return declarationsOfKind; - } - - return undefined; - } - export interface StringSymbolWriter extends SymbolWriter { string(): string; } From 8202576ab2d503258dbd18b7ebc1035607ebd173 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 09:56:13 -0800 Subject: [PATCH 28/75] Filter for enum members only. --- src/compiler/checker.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bccbede909b..9944cebf54a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,10 +5762,8 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const sourceMembers = resolveStructuredTypeMembers(getTypeOfSymbol(source.symbol)).properties; - const targetMembers = resolveStructuredTypeMembers(getTypeOfSymbol(target.symbol)).properties; - const targetNames = arrayToMap(targetMembers, member => member.name); - for (const member of sourceMembers) { + const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); + for (const member of getEnumMembersOfEnumType(source)) { if (!hasProperty(targetNames, member.name)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, member.name, @@ -5775,6 +5773,11 @@ namespace ts { } return Ternary.True; } + + function getEnumMembersOfEnumType(type: Type) { + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + property => !!(property.flags & SymbolFlags.EnumMember)); + } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From dc9d307f137dc2a7b812cea42aac6927711b419a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 11 Dec 2015 10:08:01 -0800 Subject: [PATCH 29/75] Fix lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9944cebf54a..8d9fe1f7ba5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5775,7 +5775,7 @@ namespace ts { } function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, + return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, property => !!(property.flags & SymbolFlags.EnumMember)); } } From e9dc011080e274e39f6eeecc27b5534b842739c3 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 14:10:12 -0800 Subject: [PATCH 30/75] Fixed unnecessary error in test. --- .../types/stringLiteral/stringLiteralTypesAsTags01.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts index cea04f0818e..ba189406533 100644 --- a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts @@ -20,7 +20,7 @@ function hasKind(entity: Entity, kind: "A"): entity is A; function hasKind(entity: Entity, kind: "B"): entity is B; function hasKind(entity: Entity, kind: Kind): entity is Entity; function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; + return entity.kind === kind; } let x: A = { From 8cceedd725a848e9e65002b1d4871cb54c579fb9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 14:11:45 -0800 Subject: [PATCH 31/75] Accepted baselines. --- .../stringLiteralTypesAsTags01.errors.txt | 51 -------- .../reference/stringLiteralTypesAsTags01.js | 4 +- .../stringLiteralTypesAsTags01.symbols | 112 ++++++++++++++++ .../stringLiteralTypesAsTags01.types | 121 ++++++++++++++++++ .../reference/superPropertyAccess_ES5.js | 8 +- 5 files changed, 239 insertions(+), 57 deletions(-) delete mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags01.types diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt deleted file mode 100644 index 90c8c3efdf7..00000000000 --- a/tests/baselines/reference/stringLiteralTypesAsTags01.errors.txt +++ /dev/null @@ -1,51 +0,0 @@ -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(20,10): error TS2394: Overload signature is not compatible with function implementation. -tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21): error TS2304: Cannot find name 'is'. - - -==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (2 errors) ==== - - type Kind = "A" | "B" - - interface Entity { - kind: Kind; - } - - interface A extends Entity { - kind: "A"; - a: number; - } - - interface B extends Entity { - kind: "B"; - b: string; - } - - function hasKind(entity: Entity, kind: "A"): entity is A; - function hasKind(entity: Entity, kind: "B"): entity is B; - function hasKind(entity: Entity, kind: Kind): entity is Entity; - ~~~~~~~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; - ~~ -!!! error TS2304: Cannot find name 'is'. - } - - let x: A = { - kind: "A", - a: 100, - } - - if (hasKind(x, "A")) { - let a = x; - } - else { - let b = x; - } - - if (!hasKind(x, "B")) { - let c = x; - } - else { - let d = x; - } \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.js b/tests/baselines/reference/stringLiteralTypesAsTags01.js index 3fe33ace487..b7b3872ce66 100644 --- a/tests/baselines/reference/stringLiteralTypesAsTags01.js +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.js @@ -20,7 +20,7 @@ function hasKind(entity: Entity, kind: "A"): entity is A; function hasKind(entity: Entity, kind: "B"): entity is B; function hasKind(entity: Entity, kind: Kind): entity is Entity; function hasKind(entity: Entity, kind: Kind): boolean { - return kind === is; + return entity.kind === kind; } let x: A = { @@ -44,7 +44,7 @@ else { //// [stringLiteralTypesAsTags01.js] function hasKind(entity, kind) { - return kind === is; + return entity.kind === kind; } var x = { kind: "A", diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.symbols b/tests/baselines/reference/stringLiteralTypesAsTags01.symbols new file mode 100644 index 00000000000..afdeeff71a6 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.symbols @@ -0,0 +1,112 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts === + +type Kind = "A" | "B" +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) + +interface Entity { +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: Kind; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) +} + +interface A extends Entity { +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: "A"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 7, 28)) + + a: number; +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 8, 14)) +} + +interface B extends Entity { +>B : Symbol(B, Decl(stringLiteralTypesAsTags01.ts, 10, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + + kind: "B"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 12, 28)) + + b: string; +>b : Symbol(b, Decl(stringLiteralTypesAsTags01.ts, 13, 14)) +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 17, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 17, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 17, 17)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) + +function hasKind(entity: Entity, kind: "B"): entity is B; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 18, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 18, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 18, 17)) +>B : Symbol(B, Decl(stringLiteralTypesAsTags01.ts, 10, 1)) + +function hasKind(entity: Entity, kind: Kind): entity is Entity; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 19, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 19, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 19, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) + +function hasKind(entity: Entity, kind: Kind): boolean { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 20, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags01.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 20, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags01.ts, 0, 0)) + + return entity.kind === kind; +>entity.kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags01.ts, 20, 17)) +>kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags01.ts, 3, 18)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 20, 32)) +} + +let x: A = { +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags01.ts, 5, 1)) + + kind: "A", +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags01.ts, 24, 12)) + + a: 100, +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 25, 14)) +} + +if (hasKind(x, "A")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) + + let a = x; +>a : Symbol(a, Decl(stringLiteralTypesAsTags01.ts, 30, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} +else { + let b = x; +>b : Symbol(b, Decl(stringLiteralTypesAsTags01.ts, 33, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} + +if (!hasKind(x, "B")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags01.ts, 15, 1), Decl(stringLiteralTypesAsTags01.ts, 17, 57), Decl(stringLiteralTypesAsTags01.ts, 18, 57), Decl(stringLiteralTypesAsTags01.ts, 19, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) + + let c = x; +>c : Symbol(c, Decl(stringLiteralTypesAsTags01.ts, 37, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} +else { + let d = x; +>d : Symbol(d, Decl(stringLiteralTypesAsTags01.ts, 40, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags01.ts, 24, 3)) +} diff --git a/tests/baselines/reference/stringLiteralTypesAsTags01.types b/tests/baselines/reference/stringLiteralTypesAsTags01.types new file mode 100644 index 00000000000..6966ede5482 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags01.types @@ -0,0 +1,121 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts === + +type Kind = "A" | "B" +>Kind : "A" | "B" + +interface Entity { +>Entity : Entity + + kind: Kind; +>kind : "A" | "B" +>Kind : "A" | "B" +} + +interface A extends Entity { +>A : A +>Entity : Entity + + kind: "A"; +>kind : "A" + + a: number; +>a : number +} + +interface B extends Entity { +>B : B +>Entity : Entity + + kind: "B"; +>kind : "B" + + b: string; +>b : string +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" +>entity : any +>A : A + +function hasKind(entity: Entity, kind: "B"): entity is B; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "B" +>entity : any +>B : B + +function hasKind(entity: Entity, kind: Kind): entity is Entity; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" +>entity : any +>Entity : Entity + +function hasKind(entity: Entity, kind: Kind): boolean { +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" + + return entity.kind === kind; +>entity.kind === kind : boolean +>entity.kind : "A" | "B" +>entity : Entity +>kind : "A" | "B" +>kind : "A" | "B" +} + +let x: A = { +>x : A +>A : A +>{ kind: "A", a: 100,} : { kind: "A"; a: number; } + + kind: "A", +>kind : "A" +>"A" : "A" + + a: 100, +>a : number +>100 : number +} + +if (hasKind(x, "A")) { +>hasKind(x, "A") : entity is A +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>x : A +>"A" : "A" + + let a = x; +>a : A +>x : A +} +else { + let b = x; +>b : A +>x : A +} + +if (!hasKind(x, "B")) { +>!hasKind(x, "B") : boolean +>hasKind(x, "B") : entity is B +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; (entity: Entity, kind: "A" | "B"): entity is Entity; } +>x : A +>"B" : "B" + + let c = x; +>c : A +>x : A +} +else { + let d = x; +>d : A +>x : A +} diff --git a/tests/baselines/reference/superPropertyAccess_ES5.js b/tests/baselines/reference/superPropertyAccess_ES5.js index a31c1dfdcba..63f5f6f316a 100644 --- a/tests/baselines/reference/superPropertyAccess_ES5.js +++ b/tests/baselines/reference/superPropertyAccess_ES5.js @@ -45,7 +45,7 @@ var MyBase = (function () { configurable: true }); return MyBase; -})(); +}()); var MyDerived = (function (_super) { __extends(MyDerived, _super); function MyDerived() { @@ -54,7 +54,7 @@ var MyDerived = (function (_super) { var f2 = _super.prototype.value; } return MyDerived; -})(MyBase); +}(MyBase)); var d = new MyDerived(); var f3 = d.value; var A = (function () { @@ -67,7 +67,7 @@ var A = (function () { configurable: true }); return A; -})(); +}()); var B = (function (_super) { __extends(B, _super); function B() { @@ -81,4 +81,4 @@ var B = (function (_super) { configurable: true }); return B; -})(A); +}(A)); From 3cdfc36109aff6243d22962f47fa331b8be84f8d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:02:43 -0800 Subject: [PATCH 32/75] Added tests for 'void' return type compatibilty on overloads and implementations. --- .../functions/functionOverloadCompatibilityWithVoid01.ts | 4 ++++ .../functions/functionOverloadCompatibilityWithVoid02.ts | 4 ++++ .../functions/functionOverloadCompatibilityWithVoid03.ts | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts create mode 100644 tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts new file mode 100644 index 00000000000..d973c946bb9 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts @@ -0,0 +1,4 @@ +function f(x: string): number; +function f(x: string): void { + return; +} \ No newline at end of file diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts new file mode 100644 index 00000000000..ef89d790ff7 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts @@ -0,0 +1,4 @@ +function f(x: string): void; +function f(x: string): number { + return 0; +} \ No newline at end of file diff --git a/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts new file mode 100644 index 00000000000..5f0a2327d74 --- /dev/null +++ b/tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts @@ -0,0 +1,4 @@ +function f(x: string): void; +function f(x: string): void { + return; +} \ No newline at end of file From 069fada0ce3e15622ed2da14d9c8a3edf042bde8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:04:59 -0800 Subject: [PATCH 33/75] Accepted baselines. --- ...functionOverloadCompatibilityWithVoid01.errors.txt | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid01.js | 10 ++++++++++ ...functionOverloadCompatibilityWithVoid02.errors.txt | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid02.js | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid03.js | 10 ++++++++++ .../functionOverloadCompatibilityWithVoid03.symbols | 11 +++++++++++ .../functionOverloadCompatibilityWithVoid03.types | 11 +++++++++++ 7 files changed, 72 insertions(+) create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt new file mode 100644 index 00000000000..56951e380e4 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid01.ts (1 errors) ==== + function f(x: string): number; + ~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function f(x: string): void { + return; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js new file mode 100644 index 00000000000..b2d7e64d58e --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid01.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid01.ts] +function f(x: string): number; +function f(x: string): void { + return; +} + +//// [functionOverloadCompatibilityWithVoid01.js] +function f(x) { + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt new file mode 100644 index 00000000000..33155afb5f5 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. + + +==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts (1 errors) ==== + function f(x: string): void; + ~ +!!! error TS2394: Overload signature is not compatible with function implementation. + function f(x: string): number { + return 0; + } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js new file mode 100644 index 00000000000..4f53be1f9c3 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid02.ts] +function f(x: string): void; +function f(x: string): number { + return 0; +} + +//// [functionOverloadCompatibilityWithVoid02.js] +function f(x) { + return 0; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js new file mode 100644 index 00000000000..b83939442cb --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.js @@ -0,0 +1,10 @@ +//// [functionOverloadCompatibilityWithVoid03.ts] +function f(x: string): void; +function f(x: string): void { + return; +} + +//// [functionOverloadCompatibilityWithVoid03.js] +function f(x) { + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols new file mode 100644 index 00000000000..57fe6006ced --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts === +function f(x: string): void; +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 11)) + +function f(x: string): void { +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid03.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid03.ts, 1, 11)) + + return; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types new file mode 100644 index 00000000000..74dfa28c142 --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid03.types @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid03.ts === +function f(x: string): void; +>f : (x: string) => void +>x : string + +function f(x: string): void { +>f : (x: string) => void +>x : string + + return; +} From 9b507b7512290b28bcd710a363f7a98be261a077 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:08:30 -0800 Subject: [PATCH 34/75] Specifically test for 'void' to permit implementations to return more than what was guaranteed. --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ac8a4ac89a4..a83c1027ad1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4987,7 +4987,8 @@ namespace ts { const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); - if (checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) + if (targetReturnType === voidType + || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { const anyReturningSource = cloneSignature(erasedSource); const anyReturningTarget = cloneSignature(erasedTarget); From e012645309eadc7496b26380edf49acff044fe93 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:08:45 -0800 Subject: [PATCH 35/75] Accepted baselines. --- ...unctionOverloadCompatibilityWithVoid02.errors.txt | 10 ---------- .../functionOverloadCompatibilityWithVoid02.symbols | 11 +++++++++++ .../functionOverloadCompatibilityWithVoid02.types | 12 ++++++++++++ 3 files changed, 23 insertions(+), 10 deletions(-) delete mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols create mode 100644 tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt deleted file mode 100644 index 33155afb5f5..00000000000 --- a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts(1,10): error TS2394: Overload signature is not compatible with function implementation. - - -==== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts (1 errors) ==== - function f(x: string): void; - ~ -!!! error TS2394: Overload signature is not compatible with function implementation. - function f(x: string): number { - return 0; - } \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols new file mode 100644 index 00000000000..210f7e3e4ee --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts === +function f(x: string): void; +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 11)) + +function f(x: string): number { +>f : Symbol(f, Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 0), Decl(functionOverloadCompatibilityWithVoid02.ts, 0, 28)) +>x : Symbol(x, Decl(functionOverloadCompatibilityWithVoid02.ts, 1, 11)) + + return 0; +} diff --git a/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types new file mode 100644 index 00000000000..aa6fda7222b --- /dev/null +++ b/tests/baselines/reference/functionOverloadCompatibilityWithVoid02.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/functions/functionOverloadCompatibilityWithVoid02.ts === +function f(x: string): void; +>f : (x: string) => void +>x : string + +function f(x: string): number { +>f : (x: string) => void +>x : string + + return 0; +>0 : number +} From a236461358691e9773ef02b61e3ef5fa4cc79f25 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 15:10:50 -0800 Subject: [PATCH 36/75] Reversed order of checks, since the implementation will typically be more general than the overload. --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a83c1027ad1..cd95267589b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4988,8 +4988,8 @@ namespace ts { const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType - || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined) - || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)) { + || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) + || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { const anyReturningSource = cloneSignature(erasedSource); const anyReturningTarget = cloneSignature(erasedTarget); anyReturningSource.resolvedReturnType = anyType; From 73526cf39ab2086f25e3f7157edeee0897a47973 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Dec 2015 16:01:42 -0800 Subject: [PATCH 37/75] Do some caching so that we don't repeat the same work for the implementation signature for every overload. --- src/compiler/checker.ts | 21 +++++++++++++++++---- src/compiler/types.ts | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cd95267589b..fac21177aae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4115,6 +4115,16 @@ namespace ts { return signature.erasedSignatureCache; } + function getAnyReturningErasedSignature(signature: Signature): Signature { + if (!signature.anyReturningErasedSignatureCache) { + const erasedSignature = getErasedSignature(signature); + const anyReturningErasedSignature = cloneSignature(erasedSignature); + anyReturningErasedSignature.resolvedReturnType = anyType; + signature.anyReturningErasedSignatureCache = anyReturningErasedSignature; + } + return signature.anyReturningErasedSignatureCache; + } + function getOrCreateTypeFromSignature(signature: Signature): ObjectType { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an @@ -4985,16 +4995,19 @@ namespace ts { const erasedSource = getErasedSignature(implementation); const erasedTarget = getErasedSignature(overload); + // First see if the return types are compatible in either direction. const sourceReturnType = getReturnTypeOfSignature(erasedSource); const targetReturnType = getReturnTypeOfSignature(erasedTarget); if (targetReturnType === voidType || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { - const anyReturningSource = cloneSignature(erasedSource); - const anyReturningTarget = cloneSignature(erasedTarget); - anyReturningSource.resolvedReturnType = anyType; - anyReturningTarget.resolvedReturnType = anyType; + // The return types are compatible, so create versions of the signature with 'any' as the return type. + // We need to do this so that we can check assignability while disregarding the return type. + const anyReturningSource = getAnyReturningErasedSignature(implementation); + const anyReturningTarget = getAnyReturningErasedSignature(overload); + + // Create object types to actually perform relation checks. const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ff8ffa4ebd2..c6c78709300 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2280,6 +2280,8 @@ namespace ts { /* @internal */ erasedSignatureCache?: Signature; // Erased version of signature (deferred) /* @internal */ + anyReturningErasedSignatureCache?: Signature; // A version of the erased signature whose type returns 'any' + /* @internal */ isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } From 60e1f301822daba4afa67a37ec777b4fa47b6691 Mon Sep 17 00:00:00 2001 From: vladima Date: Fri, 11 Dec 2015 17:16:28 -0800 Subject: [PATCH 38/75] allow usage of 'super' in object literal expressions --- src/compiler/checker.ts | 86 ++++++----- src/compiler/diagnosticMessages.json | 8 ++ src/compiler/utilities.ts | 54 ++++--- src/services/services.ts | 4 +- .../computedPropertyNames24_ES5.errors.txt | 4 +- .../computedPropertyNames24_ES6.errors.txt | 4 +- .../computedPropertyNames26_ES5.errors.txt | 4 +- .../computedPropertyNames26_ES6.errors.txt | 4 +- .../computedPropertyNames27_ES5.errors.txt | 4 +- .../computedPropertyNames27_ES6.errors.txt | 4 +- .../decoratorOnClassMethod12.errors.txt | 4 +- .../emitThisInSuperMethodCall.errors.txt | 12 +- .../reference/errorSuperCalls.errors.txt | 32 ++--- .../errorSuperPropertyAccess.errors.txt | 16 +-- .../superCallFromFunction1.errors.txt | 4 +- .../reference/superErrors.errors.txt | 32 ++--- .../superInObjectLiterals_ES5.errors.txt | 95 +++++++++++++ .../reference/superInObjectLiterals_ES5.js | 133 ++++++++++++++++++ .../superInObjectLiterals_ES6.errors.txt | 77 ++++++++++ .../reference/superInObjectLiterals_ES6.js | 119 ++++++++++++++++ ...essInComputedPropertiesOfNestedType_ES5.js | 46 ++++++ ...ComputedPropertiesOfNestedType_ES5.symbols | 29 ++++ ...InComputedPropertiesOfNestedType_ES5.types | 35 +++++ ...essInComputedPropertiesOfNestedType_ES6.js | 31 ++++ ...ComputedPropertiesOfNestedType_ES6.symbols | 29 ++++ ...InComputedPropertiesOfNestedType_ES6.types | 35 +++++ ...ect-literal-getters-and-setters.errors.txt | 16 +-- ...side-object-literal-getters-and-setters.js | 6 +- .../compiler/superInObjectLiterals_ES5.ts | 60 ++++++++ .../compiler/superInObjectLiterals_ES6.ts | 60 ++++++++ ...essInComputedPropertiesOfNestedType_ES5.ts | 15 ++ ...essInComputedPropertiesOfNestedType_ES6.ts | 15 ++ 32 files changed, 940 insertions(+), 137 deletions(-) create mode 100644 tests/baselines/reference/superInObjectLiterals_ES5.errors.txt create mode 100644 tests/baselines/reference/superInObjectLiterals_ES5.js create mode 100644 tests/baselines/reference/superInObjectLiterals_ES6.errors.txt create mode 100644 tests/baselines/reference/superInObjectLiterals_ES6.js create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.js create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.symbols create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.types create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.js create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.symbols create mode 100644 tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.types create mode 100644 tests/cases/compiler/superInObjectLiterals_ES5.ts create mode 100644 tests/cases/compiler/superInObjectLiterals_ES6.ts create mode 100644 tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts create mode 100644 tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76bd39a00bf..6af7ddba419 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7037,17 +7037,14 @@ namespace ts { function checkSuperExpression(node: Node): Type { const isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (node.parent).expression === node; - const classDeclaration = getContainingClass(node); - const classType = classDeclaration && getDeclaredTypeOfSymbol(getSymbolOfNode(classDeclaration)); - const baseClassType = classType && getBaseTypes(classType)[0]; - let container = getSuperContainer(node, /*includeFunctions*/ true); + let container = getSuperContainer(node, /*stopOnFunctions*/ true); let needToCaptureLexicalThis = false; if (!isCallExpression) { // adjust the container reference in case if super is used inside arrow functions with arbitrary deep nesting while (container && container.kind === SyntaxKind.ArrowFunction) { - container = getSuperContainer(container, /*includeFunctions*/ true); + container = getSuperContainer(container, /*stopOnFunctions*/ true); needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6; } } @@ -7055,43 +7052,64 @@ namespace ts { const canUseSuperExpression = isLegalUsageOfSuperExpression(container); let nodeCheckFlag: NodeCheckFlags = 0; - // always set NodeCheckFlags for 'super' expression node - if (canUseSuperExpression) { - if ((container.flags & NodeFlags.Static) || isCallExpression) { - nodeCheckFlag = NodeCheckFlags.SuperStatic; + if (!canUseSuperExpression) { + if (isCallExpression) { + error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); + } + else if (!container || !container.parent || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression)) { + error(node, Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); } else { - nodeCheckFlag = NodeCheckFlags.SuperInstance; - } - - getNodeLinks(node).flags |= nodeCheckFlag; - - if (needToCaptureLexicalThis) { - // call expressions are allowed only in constructors so they should always capture correct 'this' - // super property access expressions can also appear in arrow functions - - // in this case they should also use correct lexical this - captureLexicalThis(node.parent, container); - } - } - - if (!baseClassType) { - if (!classDeclaration || !getClassExtendsHeritageClauseElement(classDeclaration)) { - error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); + // issue more specific error if super is used in computed property name + let current = node; + while (current && current !== container && current.kind !== SyntaxKind.ComputedPropertyName) { + current = current.parent; + } + if (current && current.kind === SyntaxKind.ComputedPropertyName) { + error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); + } + else { + error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); + } } return unknownType; } - if (!canUseSuperExpression) { - if (container && container.kind === SyntaxKind.ComputedPropertyName) { - error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); - } - else if (isCallExpression) { - error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); + if ((container.flags & NodeFlags.Static) || isCallExpression) { + nodeCheckFlag = NodeCheckFlags.SuperStatic; + } + else { + nodeCheckFlag = NodeCheckFlags.SuperInstance; + } + + getNodeLinks(node).flags |= nodeCheckFlag; + + if (needToCaptureLexicalThis) { + // call expressions are allowed only in constructors so they should always capture correct 'this' + // super property access expressions can also appear in arrow functions - + // in this case they should also use correct lexical this + captureLexicalThis(node.parent, container); + } + + if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + if (languageVersion < ScriptTarget.ES6) { + error(node, Diagnostics.super_in_members_of_object_literal_expressions_is_only_allowed_when_option_target_is_ES2015_or_higher); + return unknownType; } else { - error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); + // for object literal assume that type of 'super' is 'any' + return anyType; } + } + // at this point the only legal case for parent is ClassLikeDeclaration + const classLikeDeclaration = container.parent; + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)); + const baseClassType = classType && getBaseTypes(classType)[0]; + if (!baseClassType) { + if (!getClassExtendsHeritageClauseElement(classLikeDeclaration)) { + error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); + } return unknownType; } @@ -7121,8 +7139,8 @@ namespace ts { // - In a constructor, instance member function, instance member accessor, or instance member variable initializer where this references a derived class instance // - In a static member function or static member accessor - // topmost container must be something that is directly nested in the class declaration - if (container && isClassLike(container.parent)) { + // topmost container must be something that is directly nested in the class declaration\object literal expression + if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) { if (container.flags & NodeFlags.Static) { return container.kind === SyntaxKind.MethodDeclaration || container.kind === SyntaxKind.MethodSignature || diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 54123808932..30b46e5cde2 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1759,6 +1759,14 @@ "category": "Error", "code": 2658 }, + "'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher.": { + "category": "Error", + "code": 2659 + }, + "'super' can only be referenced in members of derived classes or object literal expressions.": { + "category": "Error", + "code": 2660 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000 diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index eee09fc641f..a85432418cc 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -775,26 +775,38 @@ namespace ts { } } - export function getSuperContainer(node: Node, includeFunctions: boolean): Node { + /** + * Given an super call\property node returns a closest node where either + * - super call\property is legal in the node and not legal in the parent node the node. + * i.e. super call is legal in constructor but not legal in the class body. + * - node is arrow function (so caller might need to call getSuperContainer in case if he needs to climb higher) + * - super call\property is definitely illegal in the node (but might be legal in some subnode) + * i.e. super property access is illegal in function declaration but can be legal in the statement list + */ + export function getSuperContainer(node: Node, stopOnFunctions: boolean): Node { while (true) { node = node.parent; - if (!node) return node; + if (!node) { + return node; + } switch (node.kind) { case SyntaxKind.ComputedPropertyName: - // If the grandparent node is an object literal (as opposed to a class), - // then the computed property is not a 'super' container. - // A computed property name in a class needs to be a super container - // so that we can error on it. - if (isClassLike(node.parent.parent)) { - return node; - } - // If this is a computed property, then the parent should not - // make it a super container. The parent might be a property - // in an object literal, like a method or accessor. But in order for - // such a parent to be a super container, the reference must be in - // the *body* of the container. node = node.parent; break; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + if (!stopOnFunctions) { + continue; + } + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return node; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) { @@ -808,20 +820,6 @@ namespace ts { node = node.parent; } break; - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - if (!includeFunctions) { - continue; - } - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.Constructor: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return node; } } } diff --git a/src/services/services.ts b/src/services/services.ts index a9dda549ead..2d42172832f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5780,7 +5780,7 @@ namespace ts { } function getReferencesForSuperKeyword(superKeyword: Node): ReferencedSymbol[] { - let searchSpaceNode = getSuperContainer(superKeyword, /*includeFunctions*/ false); + let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } @@ -5815,7 +5815,7 @@ namespace ts { return; } - let container = getSuperContainer(node, /*includeFunctions*/ false); + let container = getSuperContainer(node, /*stopOnFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space diff --git a/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt index 121b39450a6..e06373fb1e3 100644 --- a/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7,6): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7,6): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts (1 errors) ==== @@ -10,5 +10,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7, class C extends Base { [super.bar()]() { } ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt index cab0ba6a85c..331723afe34 100644 --- a/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9,6): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9,6): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts (1 errors) ==== @@ -12,5 +12,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9, // use of super in static properties initializers. [super.bar()]() { } ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt index e7039712734..c8e24abfa9d 100644 --- a/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8,12): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8,12): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts (1 errors) ==== @@ -11,6 +11,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8, [ { [super.bar()]: 1 }[0] ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ]() { } } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt index d7e2b5ce7c5..ec20ed57144 100644 --- a/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10,12): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10,12): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts (1 errors) ==== @@ -13,6 +13,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10 [ { [super.bar()]: 1 }[0] ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ]() { } } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt index 1fbc7b37543..97964d48176 100644 --- a/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4,7): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4,7): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4, class C extends Base { [(super(), "prop")]() { } ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt index edf84201647..30e1ce5b14f 100644 --- a/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4,7): error TS2466: 'super' cannot be referenced in a computed property name. +tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4,7): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4, class C extends Base { [(super(), "prop")]() { } ~~~~~ -!!! error TS2466: 'super' cannot be referenced in a computed property name. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassMethod12.errors.txt b/tests/baselines/reference/decoratorOnClassMethod12.errors.txt index 3ad3cabebe2..c285d5f12c9 100644 --- a/tests/baselines/reference/decoratorOnClassMethod12.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod12.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts(6,10): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts(6,10): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts (1 errors) ==== @@ -9,7 +9,7 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod12.ts(6,10 class C extends S { @super.decorator ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. method() { } } } \ No newline at end of file diff --git a/tests/baselines/reference/emitThisInSuperMethodCall.errors.txt b/tests/baselines/reference/emitThisInSuperMethodCall.errors.txt index 06211ef771f..c8d694c8567 100644 --- a/tests/baselines/reference/emitThisInSuperMethodCall.errors.txt +++ b/tests/baselines/reference/emitThisInSuperMethodCall.errors.txt @@ -1,6 +1,6 @@ -tests/cases/compiler/emitThisInSuperMethodCall.ts(10,17): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/compiler/emitThisInSuperMethodCall.ts(17,17): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/compiler/emitThisInSuperMethodCall.ts(23,13): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/compiler/emitThisInSuperMethodCall.ts(10,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/emitThisInSuperMethodCall.ts(17,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/emitThisInSuperMethodCall.ts(23,13): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/compiler/emitThisInSuperMethodCall.ts (3 errors) ==== @@ -15,7 +15,7 @@ tests/cases/compiler/emitThisInSuperMethodCall.ts(23,13): error TS2338: 'super' function inner() { super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } }; } @@ -24,7 +24,7 @@ tests/cases/compiler/emitThisInSuperMethodCall.ts(23,13): error TS2338: 'super' () => { super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } } } @@ -32,7 +32,7 @@ tests/cases/compiler/emitThisInSuperMethodCall.ts(23,13): error TS2338: 'super' function inner() { super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } } } diff --git a/tests/baselines/reference/errorSuperCalls.errors.txt b/tests/baselines/reference/errorSuperCalls.errors.txt index 9ecc7a1565e..49bcb4b4d45 100644 --- a/tests/baselines/reference/errorSuperCalls.errors.txt +++ b/tests/baselines/reference/errorSuperCalls.errors.txt @@ -1,12 +1,12 @@ tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(4,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(9,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(14,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(18,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(22,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(26,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(30,16): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(34,9): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(38,9): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(9,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(14,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(18,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(22,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(26,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(30,16): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(34,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(38,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(46,14): error TS1034: 'super' must be followed by an argument list or member access. tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(58,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(62,9): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. @@ -27,50 +27,50 @@ tests/cases/conformance/expressions/superCalls/errorSuperCalls.ts(71,9): error T fn() { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } //super call in class accessor (get and set) with no base type get foo() { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. return null; } set foo(v) { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } //super call in class member initializer with no base type p = super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. //super call in static class member function with no base type static fn() { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } //super call in static class member initializer with no base type static k = super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. //super call in static class accessor (get and set) with no base type static get q() { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. return null; } static set q(n) { super(); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } } diff --git a/tests/baselines/reference/errorSuperPropertyAccess.errors.txt b/tests/baselines/reference/errorSuperPropertyAccess.errors.txt index c34ed912046..c54ace99f17 100644 --- a/tests/baselines/reference/errorSuperPropertyAccess.errors.txt +++ b/tests/baselines/reference/errorSuperPropertyAccess.errors.txt @@ -15,8 +15,8 @@ tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(65,23): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(68,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(69,19): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. -tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(73,13): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(76,40): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(73,13): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(76,40): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(87,15): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(91,23): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(94,9): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. @@ -34,8 +34,8 @@ tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(120,15): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(121,15): error TS2340: Only public and protected methods of the base class are accessible via the 'super' keyword. tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(122,9): error TS2341: Property 'privateStaticFunc' is private and only accessible within class 'SomeBase'. -tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(127,16): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(127,30): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(127,16): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts(127,30): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ==== tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess.ts (38 errors) ==== @@ -147,12 +147,12 @@ tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess function inner() { super.publicFunc(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } var x = { test: function () { return super.publicFunc(); } ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } } } @@ -239,7 +239,7 @@ tests/cases/conformance/expressions/superPropertyAccess/errorSuperPropertyAccess // In object literal var obj = { n: super.wat, p: super.foo() }; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. \ No newline at end of file diff --git a/tests/baselines/reference/superCallFromFunction1.errors.txt b/tests/baselines/reference/superCallFromFunction1.errors.txt index 374a3aeb16c..b993d9f1253 100644 --- a/tests/baselines/reference/superCallFromFunction1.errors.txt +++ b/tests/baselines/reference/superCallFromFunction1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/superCallFromFunction1.ts(3,5): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/superCallFromFunction1.ts(3,5): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. ==== tests/cases/compiler/superCallFromFunction1.ts (1 errors) ==== @@ -6,5 +6,5 @@ tests/cases/compiler/superCallFromFunction1.ts(3,5): error TS2335: 'super' can o function foo() { super(value => String(value)); ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. } \ No newline at end of file diff --git a/tests/baselines/reference/superErrors.errors.txt b/tests/baselines/reference/superErrors.errors.txt index 26e0ba3a6c4..5c6d7365a67 100644 --- a/tests/baselines/reference/superErrors.errors.txt +++ b/tests/baselines/reference/superErrors.errors.txt @@ -1,15 +1,15 @@ -tests/cases/compiler/superErrors.ts(3,13): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/superErrors.ts(3,13): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superErrors.ts(3,18): error TS1034: 'super' must be followed by an argument list or member access. -tests/cases/compiler/superErrors.ts(4,19): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/superErrors.ts(4,19): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superErrors.ts(4,24): error TS1034: 'super' must be followed by an argument list or member access. -tests/cases/compiler/superErrors.ts(5,31): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/superErrors.ts(5,31): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superErrors.ts(5,36): error TS1034: 'super' must be followed by an argument list or member access. -tests/cases/compiler/superErrors.ts(22,13): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/compiler/superErrors.ts(27,27): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/compiler/superErrors.ts(31,36): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/compiler/superErrors.ts(22,13): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superErrors.ts(27,27): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superErrors.ts(31,36): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superErrors.ts(31,41): error TS1034: 'super' must be followed by an argument list or member access. -tests/cases/compiler/superErrors.ts(39,27): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. -tests/cases/compiler/superErrors.ts(43,36): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/compiler/superErrors.ts(39,27): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superErrors.ts(43,36): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superErrors.ts(43,41): error TS1034: 'super' must be followed by an argument list or member access. tests/cases/compiler/superErrors.ts(47,22): error TS1034: 'super' must be followed by an argument list or member access. tests/cases/compiler/superErrors.ts(48,28): error TS1034: 'super' must be followed by an argument list or member access. @@ -21,17 +21,17 @@ tests/cases/compiler/superErrors.ts(49,40): error TS1034: 'super' must be follow // super in a non class context var x = super; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. var y = () => super; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. var z = () => () => () => super; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. } @@ -52,20 +52,20 @@ tests/cases/compiler/superErrors.ts(49,40): error TS1034: 'super' must be follow function inner() { super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } // super call in a lambda in an inner function in a constructor function inner2() { var x = () => super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } // super call in a lambda in a function expression in a constructor (function() { return () => super; })(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. } @@ -77,13 +77,13 @@ tests/cases/compiler/superErrors.ts(49,40): error TS1034: 'super' must be follow function inner() { var x = () => super.sayHello(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } // super call in a lambda in a function expression in a constructor (function() { return () => super; })(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. ~ !!! error TS1034: 'super' must be followed by an argument list or member access. } diff --git a/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt b/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt new file mode 100644 index 00000000000..944766cb5ae --- /dev/null +++ b/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt @@ -0,0 +1,95 @@ +tests/cases/compiler/superInObjectLiterals_ES5.ts(7,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(10,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(14,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(17,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES5.ts(20,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES5.ts(23,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES5.ts(39,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(42,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(46,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(49,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES5.ts(52,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + + +==== tests/cases/compiler/superInObjectLiterals_ES5.ts (11 errors) ==== + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + }, + get prop() { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + return 10; + }, + set prop(value) { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + }, + p1: function () { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p2: function f() { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p3: () => { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + } + }; + + class A { + method() { } + } + + class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + }, + get prop() { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + return 10; + }, + set prop(value) { + super.method(); + ~~~~~ +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. + }, + p1: function () { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p2: function f() { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p3: () => { + super.method(); + } + }; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/superInObjectLiterals_ES5.js b/tests/baselines/reference/superInObjectLiterals_ES5.js new file mode 100644 index 00000000000..f701ca7df7b --- /dev/null +++ b/tests/baselines/reference/superInObjectLiterals_ES5.js @@ -0,0 +1,133 @@ +//// [superInObjectLiterals_ES5.ts] +var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } +}; + +class A { + method() { } +} + +class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } + }; + } +} + +//// [superInObjectLiterals_ES5.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var obj = { + __proto__: { + method: function () { + } + }, + method: function () { + _super.prototype.method.call(this); + }, + get prop() { + _super.prototype.method.call(this); + return 10; + }, + set prop(value) { + _super.prototype.method.call(this); + }, + p1: function () { + _super.method.call(this); + }, + p2: function f() { + _super.method.call(this); + }, + p3: function () { + _super.method.call(this); + } +}; +var A = (function () { + function A() { + } + A.prototype.method = function () { }; + return A; +}()); +var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + B.prototype.f = function () { + var _this = this; + var obj = { + __proto__: { + method: function () { + } + }, + method: function () { + _super.prototype.method.call(this); + }, + get prop() { + _super.prototype.method.call(this); + return 10; + }, + set prop(value) { + _super.prototype.method.call(this); + }, + p1: function () { + _super.method.call(this); + }, + p2: function f() { + _super.method.call(this); + }, + p3: function () { + _super.prototype.method.call(_this); + } + }; + }; + return B; +}(A)); diff --git a/tests/baselines/reference/superInObjectLiterals_ES6.errors.txt b/tests/baselines/reference/superInObjectLiterals_ES6.errors.txt new file mode 100644 index 00000000000..dcd9692f5e3 --- /dev/null +++ b/tests/baselines/reference/superInObjectLiterals_ES6.errors.txt @@ -0,0 +1,77 @@ +tests/cases/compiler/superInObjectLiterals_ES6.ts(17,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES6.ts(20,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES6.ts(23,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES6.ts(49,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/compiler/superInObjectLiterals_ES6.ts(52,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + + +==== tests/cases/compiler/superInObjectLiterals_ES6.ts (5 errors) ==== + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p2: function f() { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p3: () => { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + } + }; + + class A { + method() { } + } + + class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p2: function f() { + super.method(); + ~~~~~ +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. + }, + p3: () => { + super.method(); + } + }; + } + } \ No newline at end of file diff --git a/tests/baselines/reference/superInObjectLiterals_ES6.js b/tests/baselines/reference/superInObjectLiterals_ES6.js new file mode 100644 index 00000000000..4cd62e68947 --- /dev/null +++ b/tests/baselines/reference/superInObjectLiterals_ES6.js @@ -0,0 +1,119 @@ +//// [superInObjectLiterals_ES6.ts] +var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } +}; + +class A { + method() { } +} + +class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } + }; + } +} + +//// [superInObjectLiterals_ES6.js] +var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } +}; +class A { + method() { } +} +class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } + }; + } +} diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.js b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.js new file mode 100644 index 00000000000..a91dfc76e3d --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.js @@ -0,0 +1,46 @@ +//// [superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts] +class A { + foo() { return 1; } +} + +class B extends A { + foo() { return 2; } + bar() { + return class { + [super.foo()]() { + return 100; + } + } + } +} + +//// [superPropertyAccessInComputedPropertiesOfNestedType_ES5.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var A = (function () { + function A() { + } + A.prototype.foo = function () { return 1; }; + return A; +}()); +var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + B.prototype.foo = function () { return 2; }; + B.prototype.bar = function () { + return (function () { + function class_1() { + } + class_1.prototype[_super.prototype.foo.call(this)] = function () { + return 100; + }; + return class_1; + }()); + }; + return B; +}(A)); diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.symbols b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.symbols new file mode 100644 index 00000000000..1379d50179f --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts === +class A { +>A : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 0)) + + foo() { return 1; } +>foo : Symbol(foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 2, 1)) +>A : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 0)) + + foo() { return 2; } +>foo : Symbol(foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 4, 19)) + + bar() { +>bar : Symbol(bar, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 5, 23)) + + return class { + [super.foo()]() { +>super.foo : Symbol(A.foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 9)) +>super : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 0)) +>foo : Symbol(A.foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts, 0, 9)) + + return 100; + } + } + } +} diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.types b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.types new file mode 100644 index 00000000000..d435bff69b5 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES5.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts === +class A { +>A : A + + foo() { return 1; } +>foo : () => number +>1 : number +} + +class B extends A { +>B : B +>A : A + + foo() { return 2; } +>foo : () => number +>2 : number + + bar() { +>bar : () => typeof (Anonymous class) + + return class { +>class { [super.foo()]() { return 100; } } : typeof (Anonymous class) + + [super.foo()]() { +>super.foo() : number +>super.foo : () => number +>super : A +>foo : () => number + + return 100; +>100 : number + } + } + } +} diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.js b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.js new file mode 100644 index 00000000000..825fa7682e2 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.js @@ -0,0 +1,31 @@ +//// [superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts] +class A { + foo() { return 1; } +} + +class B extends A { + foo() { return 2; } + bar() { + return class { + [super.foo()]() { + return 100; + } + } + } +} + +//// [superPropertyAccessInComputedPropertiesOfNestedType_ES6.js] +class A { + foo() { return 1; } +} +class B extends A { + foo() { return 2; } + bar() { + return class { + [super.foo()]() { + return 100; + } + } + ; + } +} diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.symbols b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.symbols new file mode 100644 index 00000000000..12446259f32 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts === +class A { +>A : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 0)) + + foo() { return 1; } +>foo : Symbol(foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 2, 1)) +>A : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 0)) + + foo() { return 2; } +>foo : Symbol(foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 4, 19)) + + bar() { +>bar : Symbol(bar, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 5, 23)) + + return class { + [super.foo()]() { +>super.foo : Symbol(A.foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 9)) +>super : Symbol(A, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 0)) +>foo : Symbol(A.foo, Decl(superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts, 0, 9)) + + return 100; + } + } + } +} diff --git a/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.types b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.types new file mode 100644 index 00000000000..817e3b73ba4 --- /dev/null +++ b/tests/baselines/reference/superPropertyAccessInComputedPropertiesOfNestedType_ES6.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts === +class A { +>A : A + + foo() { return 1; } +>foo : () => number +>1 : number +} + +class B extends A { +>B : B +>A : A + + foo() { return 2; } +>foo : () => number +>2 : number + + bar() { +>bar : () => typeof (Anonymous class) + + return class { +>class { [super.foo()]() { return 100; } } : typeof (Anonymous class) + + [super.foo()]() { +>super.foo() : number +>super.foo : () => number +>super : A +>foo : () => number + + return 100; +>100 : number + } + } + } +} diff --git a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt index 4f1faf78a78..16a66bf6fa4 100644 --- a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt +++ b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt @@ -1,10 +1,10 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(5,20): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(5,20): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(8,13): error TS2335: 'super' can only be referenced in a derived class. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(11,20): error TS2335: 'super' can only be referenced in a derived class. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(8,13): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(11,20): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(20,17): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. ==== tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts (7 errors) ==== @@ -16,19 +16,19 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. return super._foo; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. }, set foo(value: string) { ~~~ !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. super._foo = value; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. }, test: function () { return super._foo; ~~~~~ -!!! error TS2335: 'super' can only be referenced in a derived class. +!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. } } } @@ -42,7 +42,7 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. return super.test(); ~~~~~ -!!! error TS2338: 'super' property access is permitted only in a constructor, member function, or member accessor of a derived class. +!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. } }; } diff --git a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.js b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.js index be70ee33183..db6db37ac8a 100644 --- a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.js +++ b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.js @@ -38,10 +38,10 @@ var ObjectLiteral; var ThisInObjectLiteral = { _foo: '1', get foo() { - return _super._foo; + return _super.prototype._foo; }, set foo(value) { - _super._foo = value; + _super.prototype._foo = value; }, test: function () { return _super._foo; @@ -62,7 +62,7 @@ var SuperObjectTest = (function (_super) { SuperObjectTest.prototype.testing = function () { var test = { get F() { - return _super.test.call(this); + return _super.prototype.test.call(this); } }; }; diff --git a/tests/cases/compiler/superInObjectLiterals_ES5.ts b/tests/cases/compiler/superInObjectLiterals_ES5.ts new file mode 100644 index 00000000000..96cdfaa5b7b --- /dev/null +++ b/tests/cases/compiler/superInObjectLiterals_ES5.ts @@ -0,0 +1,60 @@ +// @target: ES5 +var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } +}; + +class A { + method() { } +} + +class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } + }; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/superInObjectLiterals_ES6.ts b/tests/cases/compiler/superInObjectLiterals_ES6.ts new file mode 100644 index 00000000000..05b2853a90b --- /dev/null +++ b/tests/cases/compiler/superInObjectLiterals_ES6.ts @@ -0,0 +1,60 @@ +// @target: ES6 +var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } +}; + +class A { + method() { } +} + +class B extends A { + f() { + var obj = { + __proto__: { + method() { + } + }, + method() { + super.method(); + }, + get prop() { + super.method(); + return 10; + }, + set prop(value) { + super.method(); + }, + p1: function () { + super.method(); + }, + p2: function f() { + super.method(); + }, + p3: () => { + super.method(); + } + }; + } +} \ No newline at end of file diff --git a/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts b/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts new file mode 100644 index 00000000000..9c7d28f96a4 --- /dev/null +++ b/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES5.ts @@ -0,0 +1,15 @@ +// @target: ES5 +class A { + foo() { return 1; } +} + +class B extends A { + foo() { return 2; } + bar() { + return class { + [super.foo()]() { + return 100; + } + } + } +} \ No newline at end of file diff --git a/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts b/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts new file mode 100644 index 00000000000..6a8c2e1a7d6 --- /dev/null +++ b/tests/cases/compiler/superPropertyAccessInComputedPropertiesOfNestedType_ES6.ts @@ -0,0 +1,15 @@ +// @target: ES6 +class A { + foo() { return 1; } +} + +class B extends A { + foo() { return 2; } + bar() { + return class { + [super.foo()]() { + return 100; + } + } + } +} \ No newline at end of file From 0f3eb0a058cee9a858c8d17fdc74e5d1494d4e3a Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 11 Dec 2015 19:27:24 -0800 Subject: [PATCH 39/75] Initial fix for rename for parameter property declaration --- src/compiler/binder.ts | 5 +---- src/compiler/checker.ts | 11 +++++++++++ src/compiler/types.ts | 1 + src/compiler/utilities.ts | 6 ++++++ src/services/services.ts | 11 +++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2682a5938d1..9ce8b4f4eda 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1444,10 +1444,7 @@ namespace ts { // If this is a property-parameter, then also declare the property symbol into the // containing class. - if (node.flags & NodeFlags.AccessibilityModifier && - node.parent.kind === SyntaxKind.Constructor && - isClassLike(node.parent.parent)) { - + if (isPropertyParameterDeclaration(node)) { const classDeclaration = node.parent.parent; declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7d4bfb43de7..57c4353baf1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -67,6 +67,7 @@ namespace ts { // The language service will always care about the narrowed type of a symbol, because that is // the type the language says the symbol should have. getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, + getSymbolOfParameterPropertyDeclaration, getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType, @@ -427,6 +428,16 @@ namespace ts { } // return undefined if we can't find a symbol. } + + function getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[] { + const constructoDeclaration = parameter.parent; + const classDeclaration = parameter.parent.parent; + + const parameterSymbol = getSymbol(constructoDeclaration.locals, parameterName, SymbolFlags.Value); + const propertySymbol = getSymbol(classDeclaration.symbol.members, parameterName, SymbolFlags.Value); + + return parameterSymbol && propertySymbol ? [parameterSymbol, propertySymbol] : undefined; + } function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { const declarationFile = getSourceFileOfNode(declaration); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ff8ffa4ebd2..4c1fb2bb1cd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1723,6 +1723,7 @@ namespace ts { getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol; + getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; getShorthandAssignmentValueSymbol(location: Node): Symbol; getTypeAtLocation(node: Node): Type; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index eee09fc641f..472225d31e5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2741,4 +2741,10 @@ namespace ts { } } } + + export function isPropertyParameterDeclaration(node: ParameterDeclaration): boolean { + // If this is a property-parameter, then also declare the property symbol into the + // containing class. + return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); + } } diff --git a/src/services/services.ts b/src/services/services.ts index a9dda549ead..4f2af5c35c4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5967,6 +5967,15 @@ namespace ts { } } + // If the symbol.valueDeclaration is a property parameter declaration, + // we should include both parameter declaration symbol and property declaration symbol + // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in contructor.locals. + // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members + if (symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.Parameter && + isPropertyParameterDeclaration(symbol.valueDeclaration)) { + result = result.concat(typeChecker.getSymbolOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); + } + // If this is a union property, add all the symbols from all its source symbols in all unioned types. // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { @@ -6036,6 +6045,8 @@ namespace ts { }); } + // If the reference + // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) // Or a union property, use its underlying unioned symbols return forEach(typeChecker.getRootSymbols(referenceSymbol), rootSymbol => { From af65e86aaa9cbc28ac9cc767d12f74864de52f28 Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 11 Dec 2015 19:28:21 -0800 Subject: [PATCH 40/75] Add tests --- .../renameParameterPropertyDeclaration.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/cases/fourslash/renameParameterPropertyDeclaration.ts diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration.ts new file mode 100644 index 00000000000..34d8c9ef428 --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration.ts @@ -0,0 +1,17 @@ +/// + +//// class Foo { +//// constructor(private privateParam: number, +//// public publicParam: string, +//// protected protectedParam: boolean) { +//// +//// let localPrivate = privateParam; +//// this.privateParam += 10; +//// +//// let localPublic = publicParam; +//// this.publicParam += " Hello!"; +//// +//// let localProtected = protectedParam; +//// this.protectedParam = !this.protectedParam; +//// } +//// } \ No newline at end of file From b00fa42dea98cdf3c9fd00923b6cd2a5ba288131 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 12 Dec 2015 15:52:55 -0800 Subject: [PATCH 41/75] Update tests --- ...HighlightAtParameterPropertyDeclaration.ts | 24 +++++++++++++++++++ ...indAllRefsParameterPropertyDeclaration1.ts | 18 ++++++++++++++ ...indAllRefsParameterPropertyDeclaration2.ts | 18 ++++++++++++++ ...indAllRefsParameterPropertyDeclaration3.ts | 18 ++++++++++++++ ...referenceInParameterPropertyDeclaration.ts | 24 +++++++++++++++++++ .../renameParameterPropertyDeclaration.ts | 17 ------------- .../renameParameterPropeterDeclaration1.ts | 14 +++++++++++ .../renameParameterPropeterDeclaration2.ts | 14 +++++++++++ .../renameParameterPropeterDeclaration3.ts | 14 +++++++++++ 9 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts create mode 100644 tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts create mode 100644 tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts create mode 100644 tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts create mode 100644 tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts delete mode 100644 tests/cases/fourslash/renameParameterPropertyDeclaration.ts create mode 100644 tests/cases/fourslash/renameParameterPropeterDeclaration1.ts create mode 100644 tests/cases/fourslash/renameParameterPropeterDeclaration2.ts create mode 100644 tests/cases/fourslash/renameParameterPropeterDeclaration3.ts diff --git a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts new file mode 100644 index 00000000000..aeccd252fe9 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts @@ -0,0 +1,24 @@ +/// + +// @Filename: file1.ts +//// class Foo { +//// constructor(private /*0*/privateParam: number, +//// public /*1*/publicParam: string, +//// protected /*2*/protectedParam: boolean) { +//// +//// let localPrivate = /*3*/privateParam; +//// this./*4*/privateParam += 10; +//// +//// let localPublic = /*5*/publicParam; +//// this./*6*/publicParam += " Hello!"; +//// +//// let localProtected = /*7*/protectedParam; +//// this./*8*/protectedParam = false; +//// } +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts new file mode 100644 index 00000000000..d0854262828 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -0,0 +1,18 @@ +/// + +//// class Foo { +//// constructor(private |privateParam|: number) { +//// let localPrivate = |privateParam|; +//// this.|privateParam| += 10; +//// } +//// } + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts new file mode 100644 index 00000000000..7e59567364a --- /dev/null +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -0,0 +1,18 @@ +/// + +//// class Foo { +//// constructor(public |publicParam|: number) { +//// let localPublic = |publicParam|; +//// this.|publicParam| += 10; +//// } +//// } + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts new file mode 100644 index 00000000000..2d78e9793f7 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -0,0 +1,18 @@ +/// + +//// class Foo { +//// constructor(protected |protectedParam|: number) { +//// let localProtected = |protectedParam|; +//// this.|protectedParam| += 10; +//// } +//// } + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts b/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts new file mode 100644 index 00000000000..4e86e7a4915 --- /dev/null +++ b/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts @@ -0,0 +1,24 @@ +/// + +// @Filename: file1.ts +//// class Foo { +//// constructor(private /*0*/privateParam: number, +//// public /*1*/publicParam: string, +//// protected /*2*/protectedParam: boolean) { +//// +//// let localPrivate = /*3*/privateParam; +//// this./*4*/privateParam += 10; +//// +//// let localPublic = /*5*/publicParam; +//// this./*6*/publicParam += " Hello!"; +//// +//// let localProtected = /*7*/protectedParam; +//// this./*8*/protectedParam = false; +//// } +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.referencesCountIs(3); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration.ts deleted file mode 100644 index 34d8c9ef428..00000000000 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -//// class Foo { -//// constructor(private privateParam: number, -//// public publicParam: string, -//// protected protectedParam: boolean) { -//// -//// let localPrivate = privateParam; -//// this.privateParam += 10; -//// -//// let localPublic = publicParam; -//// this.publicParam += " Hello!"; -//// -//// let localProtected = protectedParam; -//// this.protectedParam = !this.protectedParam; -//// } -//// } \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration1.ts b/tests/cases/fourslash/renameParameterPropeterDeclaration1.ts new file mode 100644 index 00000000000..1faed546d91 --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropeterDeclaration1.ts @@ -0,0 +1,14 @@ +/// + +//// class Foo { +//// constructor(private |privateParam|: number) { +//// let localPrivate = |privateParam|; +//// this.|privateParam| += 10; +//// } +//// } + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration2.ts b/tests/cases/fourslash/renameParameterPropeterDeclaration2.ts new file mode 100644 index 00000000000..e8eec5d3a0a --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropeterDeclaration2.ts @@ -0,0 +1,14 @@ +/// + +//// class Foo { +//// constructor(public |publicParam|: number) { +//// let publicParam = |publicParam|; +//// this.|publicParam| += 10; +//// } +//// } + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration3.ts b/tests/cases/fourslash/renameParameterPropeterDeclaration3.ts new file mode 100644 index 00000000000..44f4cf68858 --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropeterDeclaration3.ts @@ -0,0 +1,14 @@ +/// + +//// class Foo { +//// constructor(protected |protectedParam|: number) { +//// let protectedParam = |protectedParam|; +//// this.|protectedParam| += 10; +//// } +//// } + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file From 94c3d27f411b4f72d8f6adb422e98d38324b23e6 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 12 Dec 2015 15:53:04 -0800 Subject: [PATCH 42/75] Fix linting --- src/compiler/checker.ts | 6 +++--- src/compiler/utilities.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 57c4353baf1..1646b51702a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -428,14 +428,14 @@ namespace ts { } // return undefined if we can't find a symbol. } - + function getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[] { const constructoDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; - + const parameterSymbol = getSymbol(constructoDeclaration.locals, parameterName, SymbolFlags.Value); const propertySymbol = getSymbol(classDeclaration.symbol.members, parameterName, SymbolFlags.Value); - + return parameterSymbol && propertySymbol ? [parameterSymbol, propertySymbol] : undefined; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 472225d31e5..566a578cedf 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2741,7 +2741,7 @@ namespace ts { } } } - + export function isPropertyParameterDeclaration(node: ParameterDeclaration): boolean { // If this is a property-parameter, then also declare the property symbol into the // containing class. From b44f6e47d653419b1f47baf6734bd0942a3f15d0 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 12 Dec 2015 15:56:43 -0800 Subject: [PATCH 43/75] Simplify deferred checking of function, class, and accessor bodies. --- src/compiler/checker.ts | 155 +++++++++++----------------------------- 1 file changed, 40 insertions(+), 115 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea23255472d..e4cf101946a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -161,6 +161,8 @@ namespace ts { let jsxElementClassType: Type; + let deferredNodes: Node[]; + const tupleTypes: Map = {}; const unionTypes: Map = {}; const intersectionTypes: Map = {}; @@ -10123,6 +10125,7 @@ namespace ts { if (!contextChecked) { checkSignatureDeclaration(node); + checkNodeDeferred(node); } } } @@ -10135,7 +10138,7 @@ namespace ts { return type; } - function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) { + function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const isAsync = isAsyncFunctionLike(node); @@ -10178,8 +10181,6 @@ namespace ts { checkTypeAssignableTo(exprType, returnOrPromisedType, node.body); } } - - checkFunctionAndClassExpressionBodies(node.body); } } } @@ -11428,13 +11429,13 @@ namespace ts { if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) { checkSourceElement(node.body); } + else { + checkNodeDeferred(node); + } } - function checkObjectLiteralAccessorBody(node: AccessorDeclaration) { - if (node.body) { - checkSourceElement(node.body); - checkFunctionAndClassExpressionBodies(node.body); - } + function checkAccessorDeferred(node: AccessorDeclaration) { + checkSourceElement(node.body); } function checkMissingDeclaration(node: Node) { @@ -12373,11 +12374,7 @@ namespace ts { if (node.kind === SyntaxKind.Block) { checkGrammarStatementInAmbientContext(node); } - forEach(node.statements, checkSourceElement); - if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) { - checkFunctionAndClassExpressionBodies(node); - } } function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { @@ -13406,15 +13403,19 @@ namespace ts { function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); + checkNodeDeferred(node); return getTypeOfSymbol(getSymbolOfNode(node)); } + function checkClassExpressionDeferred(node: ClassExpression) { + forEach(node.members, checkSourceElement); + } + function checkClassDeclaration(node: ClassDeclaration) { if (!node.name && !(node.flags & NodeFlags.Default)) { grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); - forEach(node.members, checkSourceElement); } @@ -14478,107 +14479,29 @@ namespace ts { // Here, performing a full type check of the body of the function expression whilst in the process of // determining the type of foo would cause foo to be given type any because of the recursive reference. // Delaying the type check of the body ensures foo has been assigned a type. - function checkFunctionAndClassExpressionBodies(node: Node): void { - switch (node.kind) { - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - forEach((node).parameters, checkFunctionAndClassExpressionBodies); - checkFunctionExpressionOrObjectLiteralMethodBody(node); - break; - case SyntaxKind.ClassExpression: - forEach((node).members, checkSourceElement); - forEachChild(node, checkFunctionAndClassExpressionBodies); - break; - case SyntaxKind.MethodDeclaration: - case SyntaxKind.MethodSignature: - forEach(node.decorators, checkFunctionAndClassExpressionBodies); - forEach((node).parameters, checkFunctionAndClassExpressionBodies); - if (isObjectLiteralMethod(node)) { - checkFunctionExpressionOrObjectLiteralMethodBody(node); - } - break; - case SyntaxKind.Constructor: - case SyntaxKind.FunctionDeclaration: - forEach((node).parameters, checkFunctionAndClassExpressionBodies); - break; - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - forEach((node).parameters, checkFunctionAndClassExpressionBodies); - if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) { - checkObjectLiteralAccessorBody(node); - } - break; - case SyntaxKind.WithStatement: - checkFunctionAndClassExpressionBodies((node).expression); - break; - case SyntaxKind.Decorator: - case SyntaxKind.Parameter: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertySignature: - case SyntaxKind.ObjectBindingPattern: - case SyntaxKind.ArrayBindingPattern: - case SyntaxKind.BindingElement: - case SyntaxKind.ArrayLiteralExpression: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.PropertyAssignment: - case SyntaxKind.PropertyAccessExpression: - case SyntaxKind.ElementAccessExpression: - case SyntaxKind.CallExpression: - case SyntaxKind.NewExpression: - case SyntaxKind.TaggedTemplateExpression: - case SyntaxKind.TemplateExpression: - case SyntaxKind.TemplateSpan: - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.ParenthesizedExpression: - case SyntaxKind.TypeOfExpression: - case SyntaxKind.VoidExpression: - case SyntaxKind.AwaitExpression: - case SyntaxKind.DeleteExpression: - case SyntaxKind.PrefixUnaryExpression: - case SyntaxKind.PostfixUnaryExpression: - case SyntaxKind.BinaryExpression: - case SyntaxKind.ConditionalExpression: - case SyntaxKind.SpreadElementExpression: - case SyntaxKind.YieldExpression: - case SyntaxKind.Block: - case SyntaxKind.ModuleBlock: - case SyntaxKind.VariableStatement: - case SyntaxKind.ExpressionStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.BreakStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.CaseBlock: - case SyntaxKind.CaseClause: - case SyntaxKind.DefaultClause: - case SyntaxKind.LabeledStatement: - case SyntaxKind.ThrowStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.CatchClause: - case SyntaxKind.VariableDeclaration: - case SyntaxKind.VariableDeclarationList: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.HeritageClause: - case SyntaxKind.ExpressionWithTypeArguments: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.EnumMember: - case SyntaxKind.ExportAssignment: - case SyntaxKind.SourceFile: - case SyntaxKind.JsxExpression: - case SyntaxKind.JsxElement: - case SyntaxKind.JsxSelfClosingElement: - case SyntaxKind.JsxAttribute: - case SyntaxKind.JsxSpreadAttribute: - case SyntaxKind.JsxOpeningElement: - forEachChild(node, checkFunctionAndClassExpressionBodies); - break; + function checkNodeDeferred(node: Node) { + if (deferredNodes) { + deferredNodes.push(node); + } + } + + function checkDeferredNodes() { + for (const node of deferredNodes) { + switch (node.kind) { + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + checkFunctionExpressionOrObjectLiteralMethodDeferred(node); + break; + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + checkAccessorDeferred(node); + break; + case SyntaxKind.ClassExpression: + checkClassExpressionDeferred(node); + break; + } } } @@ -14613,8 +14536,10 @@ namespace ts { emitAwaiter = false; potentialThisCollisions.length = 0; + deferredNodes = []; forEach(node.statements, checkSourceElement); - checkFunctionAndClassExpressionBodies(node); + checkDeferredNodes(); + deferredNodes = undefined; if (isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); From 91b93439f12a911bc83fbc3399a9a739a619721a Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 12 Dec 2015 15:57:39 -0800 Subject: [PATCH 44/75] Accepting new baselines --- ...nePropertyAccessAndArrowFunctionIndent1.errors.txt | 11 +---------- .../multiLinePropertyAccessAndArrowFunctionIndent1.js | 3 +-- ...atementIsNotAMemberVariableDeclaration1.errors.txt | 5 +---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt b/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt index abf11dc9dba..48a1da7d22c 100644 --- a/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt +++ b/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt @@ -1,20 +1,11 @@ tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body. -tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,18): error TS2304: Cannot find name 'role'. -tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(2,18): error TS2304: Cannot find name 'Role'. -tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(4,26): error TS2503: Cannot find namespace 'ng'. -==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (4 errors) ==== +==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (1 errors) ==== return this.edit(role) ~~~~~~ !!! error TS1108: A 'return' statement can only be used within a function body. - ~~~~ -!!! error TS2304: Cannot find name 'role'. .then((role: Role) => - ~~~~ -!!! error TS2304: Cannot find name 'Role'. this.roleService.add(role) .then((data: ng.IHttpPromiseCallbackArg) => data.data)); - ~~ -!!! error TS2503: Cannot find namespace 'ng'. \ No newline at end of file diff --git a/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.js b/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.js index 2ada9f1bb52..4821f1fe69c 100644 --- a/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.js +++ b/tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.js @@ -6,9 +6,8 @@ return this.edit(role) //// [multiLinePropertyAccessAndArrowFunctionIndent1.js] -var _this = this; return this.edit(role) .then(function (role) { - return _this.roleService.add(role) + return this.roleService.add(role) .then(function (data) { return data.data; }); }); diff --git a/tests/baselines/reference/parserStatementIsNotAMemberVariableDeclaration1.errors.txt b/tests/baselines/reference/parserStatementIsNotAMemberVariableDeclaration1.errors.txt index 72cfee58e54..0532fd28d63 100644 --- a/tests/baselines/reference/parserStatementIsNotAMemberVariableDeclaration1.errors.txt +++ b/tests/baselines/reference/parserStatementIsNotAMemberVariableDeclaration1.errors.txt @@ -1,8 +1,7 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(6,5): error TS2304: Cannot find name 'private'. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (1 errors) ==== return { ~~~~~~ !!! error TS1108: A 'return' statement can only be used within a function body. @@ -11,8 +10,6 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMe // 'private' should not be considered a member variable here. private[key] = value; - ~~~~~~~ -!!! error TS2304: Cannot find name 'private'. } From f138953d887f8e5fd37af81e66adab662039bdba Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 12 Dec 2015 16:13:30 -0800 Subject: [PATCH 45/75] Fix comment --- src/compiler/checker.ts | 8 +++++++- src/services/services.ts | 2 -- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 31665734167..a2338c5ba5b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -429,7 +429,13 @@ namespace ts { // return undefined if we can't find a symbol. } - function getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[] { + /** + * Get symbols that represent parameter-property-declaration as parameter and as property declaration + * @param parameter a parameterDeclaration node + * @param parameterName a name of the parameter to get the symbols for. + * @return a tuple of two symbols + */ + function getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): [Symbol, Symbol] { const constructoDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; diff --git a/src/services/services.ts b/src/services/services.ts index 4f2af5c35c4..6728c0d5ebc 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6045,8 +6045,6 @@ namespace ts { }); } - // If the reference - // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening) // Or a union property, use its underlying unioned symbols return forEach(typeChecker.getRootSymbols(referenceSymbol), rootSymbol => { From 99722e442cb2e0bd018f133cad04afd29cc8c756 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 12 Dec 2015 16:38:11 -0800 Subject: [PATCH 46/75] Add tests for binding pattern in parameter property declaration --- ...ghlightAtParameterPropertyDeclaration1.ts} | 0 ...ighlightAtParameterPropertyDeclaration2.ts | 24 +++++++++++++++++++ ...ighlightAtParameterPropertyDeclaration3.ts | 24 +++++++++++++++++++ ...=> renameParameterPropertyDeclaration1.ts} | 0 ...=> renameParameterPropertyDeclaration2.ts} | 0 ...=> renameParameterPropertyDeclaration3.ts} | 0 .../renameParameterPropertyDeclaration4.ts | 13 ++++++++++ .../renameParameterPropertyDeclaration5.ts | 13 ++++++++++ 8 files changed, 74 insertions(+) rename tests/cases/fourslash/{documentHighlightAtParameterPropertyDeclaration.ts => documentHighlightAtParameterPropertyDeclaration1.ts} (100%) create mode 100644 tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts create mode 100644 tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration3.ts rename tests/cases/fourslash/{renameParameterPropeterDeclaration1.ts => renameParameterPropertyDeclaration1.ts} (100%) rename tests/cases/fourslash/{renameParameterPropeterDeclaration2.ts => renameParameterPropertyDeclaration2.ts} (100%) rename tests/cases/fourslash/{renameParameterPropeterDeclaration3.ts => renameParameterPropertyDeclaration3.ts} (100%) create mode 100644 tests/cases/fourslash/renameParameterPropertyDeclaration4.ts create mode 100644 tests/cases/fourslash/renameParameterPropertyDeclaration5.ts diff --git a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration1.ts similarity index 100% rename from tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration.ts rename to tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration1.ts diff --git a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts new file mode 100644 index 00000000000..2658dd56371 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts @@ -0,0 +1,24 @@ +/// + +// @Filename: file1.ts +//// class Foo { +//// constructor(private {/*0*/privateParam}: number, +//// public {/*1*/publicParam}: string, +//// protected {/*2*/protectedParam}: boolean) { +//// +//// let localPrivate = /*3*/privateParam; +//// this.privateParam += 10; // this is not valid syntax +//// +//// let localPublic = /*4*/publicParam; +//// this.publicParam += " Hello!"; // this is not valid syntax +//// +//// let localProtected = /*5*/protectedParam; +//// this.protectedParam = false; // this is not valid syntax +//// } +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); +} \ No newline at end of file diff --git a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration3.ts b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration3.ts new file mode 100644 index 00000000000..958e3bb45c9 --- /dev/null +++ b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration3.ts @@ -0,0 +1,24 @@ +/// + +// @Filename: file1.ts +//// class Foo { +//// constructor(private [/*0*/privateParam]: number, +//// public [/*1*/publicParam]: string, +//// protected [/*2*/protectedParam]: boolean) { +//// +//// let localPrivate = /*3*/privateParam; +//// this.privateParam += 10; // this is not valid syntax +//// +//// let localPublic = /*4*/publicParam; +//// this.publicParam += " Hello!"; // this is not valid syntax +//// +//// let localProtected = /*5*/protectedParam; +//// this.protectedParam = false; // this is not valid syntax +//// } +//// } + +let markers = test.markers() +for (let marker of markers) { + goTo.position(marker.position); + verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration1.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts similarity index 100% rename from tests/cases/fourslash/renameParameterPropeterDeclaration1.ts rename to tests/cases/fourslash/renameParameterPropertyDeclaration1.ts diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration2.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts similarity index 100% rename from tests/cases/fourslash/renameParameterPropeterDeclaration2.ts rename to tests/cases/fourslash/renameParameterPropertyDeclaration2.ts diff --git a/tests/cases/fourslash/renameParameterPropeterDeclaration3.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts similarity index 100% rename from tests/cases/fourslash/renameParameterPropeterDeclaration3.ts rename to tests/cases/fourslash/renameParameterPropertyDeclaration3.ts diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts new file mode 100644 index 00000000000..21ba7da4141 --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts @@ -0,0 +1,13 @@ +/// + +//// class Foo { +//// constructor(protected { |protectedParam| }) { +//// let myProtectedParam = |protectedParam|; +//// } +//// } + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts new file mode 100644 index 00000000000..a4bc00b697b --- /dev/null +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts @@ -0,0 +1,13 @@ +/// + +//// class Foo { +//// constructor(protected [ |protectedParam| ]) { +//// let myProtectedParam = |protectedParam|; +//// } +//// } + +let ranges = test.ranges() +for (let range of ranges) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file From b65c5779a2e543c26849e4eb07d09fc849e07c87 Mon Sep 17 00:00:00 2001 From: vladima Date: Sat, 12 Dec 2015 23:07:18 -0800 Subject: [PATCH 47/75] addressed PR feedback --- src/compiler/checker.ts | 26 ++++++++++--------- .../computedPropertyNames24_ES5.errors.txt | 4 +-- .../computedPropertyNames24_ES6.errors.txt | 4 +-- .../computedPropertyNames26_ES5.errors.txt | 4 +-- .../computedPropertyNames26_ES6.errors.txt | 4 +-- .../computedPropertyNames27_ES5.errors.txt | 4 +-- .../computedPropertyNames27_ES6.errors.txt | 4 +-- .../computedPropertyNames30_ES5.errors.txt | 4 +-- .../computedPropertyNames30_ES6.errors.txt | 4 +-- 9 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6af7ddba419..2dd567cbe90 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7053,24 +7053,26 @@ namespace ts { let nodeCheckFlag: NodeCheckFlags = 0; if (!canUseSuperExpression) { - if (isCallExpression) { + // issue more specific error if super is used in computed property name + // class A { foo() { return "1" }} + // class B { + // [super.foo()]() {} + // } + let current = node; + while (current && current !== container && current.kind !== SyntaxKind.ComputedPropertyName) { + current = current.parent; + } + if (current && current.kind === SyntaxKind.ComputedPropertyName) { + error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); + } + else if (isCallExpression) { error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); } else if (!container || !container.parent || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression)) { error(node, Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); } else { - // issue more specific error if super is used in computed property name - let current = node; - while (current && current !== container && current.kind !== SyntaxKind.ComputedPropertyName) { - current = current.parent; - } - if (current && current.kind === SyntaxKind.ComputedPropertyName) { - error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); - } - else { - error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); - } + error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); } return unknownType; } diff --git a/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt index e06373fb1e3..121b39450a6 100644 --- a/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames24_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7,6): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7,6): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts (1 errors) ==== @@ -10,5 +10,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES5.ts(7, class C extends Base { [super.bar()]() { } ~~~~~ -!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +!!! error TS2466: 'super' cannot be referenced in a computed property name. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt index 331723afe34..cab0ba6a85c 100644 --- a/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames24_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9,6): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9,6): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts (1 errors) ==== @@ -12,5 +12,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames24_ES6.ts(9, // use of super in static properties initializers. [super.bar()]() { } ~~~~~ -!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +!!! error TS2466: 'super' cannot be referenced in a computed property name. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt index c8e24abfa9d..e7039712734 100644 --- a/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames26_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8,12): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8,12): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts (1 errors) ==== @@ -11,6 +11,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES5.ts(8, [ { [super.bar()]: 1 }[0] ~~~~~ -!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +!!! error TS2466: 'super' cannot be referenced in a computed property name. ]() { } } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt index ec20ed57144..d7e2b5ce7c5 100644 --- a/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames26_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10,12): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10,12): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts (1 errors) ==== @@ -13,6 +13,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames26_ES6.ts(10 [ { [super.bar()]: 1 }[0] ~~~~~ -!!! error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. +!!! error TS2466: 'super' cannot be referenced in a computed property name. ]() { } } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt index 97964d48176..1fbc7b37543 100644 --- a/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames27_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4,7): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4,7): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES5.ts(4, class C extends Base { [(super(), "prop")]() { } ~~~~~ -!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +!!! error TS2466: 'super' cannot be referenced in a computed property name. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt index 30e1ce5b14f..edf84201647 100644 --- a/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames27_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4,7): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4,7): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames27_ES6.ts(4, class C extends Base { [(super(), "prop")]() { } ~~~~~ -!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +!!! error TS2466: 'super' cannot be referenced in a computed property name. } \ No newline at end of file diff --git a/tests/baselines/reference/computedPropertyNames30_ES5.errors.txt b/tests/baselines/reference/computedPropertyNames30_ES5.errors.txt index deb80dbcca8..e64b83f609e 100644 --- a/tests/baselines/reference/computedPropertyNames30_ES5.errors.txt +++ b/tests/baselines/reference/computedPropertyNames30_ES5.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES5.ts(11,19): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES5.ts(11,19): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES5.ts (1 errors) ==== @@ -14,7 +14,7 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES5.ts(11 //treatment of other similar violations. [(super(), "prop")]() { } ~~~~~ -!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +!!! error TS2466: 'super' cannot be referenced in a computed property name. }; } } diff --git a/tests/baselines/reference/computedPropertyNames30_ES6.errors.txt b/tests/baselines/reference/computedPropertyNames30_ES6.errors.txt index b10d184f799..a5771629ac2 100644 --- a/tests/baselines/reference/computedPropertyNames30_ES6.errors.txt +++ b/tests/baselines/reference/computedPropertyNames30_ES6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES6.ts(11,19): error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES6.ts(11,19): error TS2466: 'super' cannot be referenced in a computed property name. ==== tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES6.ts (1 errors) ==== @@ -14,7 +14,7 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames30_ES6.ts(11 //treatment of other similar violations. [(super(), "prop")]() { } ~~~~~ -!!! error TS2337: Super calls are not permitted outside constructors or in nested functions inside constructors. +!!! error TS2466: 'super' cannot be referenced in a computed property name. }; } } From e354aec8a38a4a173fce8b242af3484bc9e72bb4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 13 Dec 2015 18:25:45 -0800 Subject: [PATCH 48/75] Mark anonymous type as resolved before resolving call signatures --- src/compiler/checker.ts | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ea23255472d..cf52531d6f5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3608,37 +3608,29 @@ namespace ts { function resolveAnonymousTypeMembers(type: AnonymousType) { const symbol = type.symbol; - let members: SymbolTable; - let callSignatures: Signature[]; - let constructSignatures: Signature[]; - let stringIndexType: Type; - let numberIndexType: Type; - if (type.target) { - members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); - callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature); - constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature); - stringIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.String), type.mapper); - numberIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.Number), type.mapper); + const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false); + const callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature); + const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature); + const stringIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.String), type.mapper); + const numberIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.Number), type.mapper); + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); } else if (symbol.flags & SymbolFlags.TypeLiteral) { - members = symbol.members; - callSignatures = getSignaturesOfSymbol(members["__call"]); - constructSignatures = getSignaturesOfSymbol(members["__new"]); - stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); - numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + const members = symbol.members; + const callSignatures = getSignaturesOfSymbol(members["__call"]); + const constructSignatures = getSignaturesOfSymbol(members["__new"]); + const stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String); + const numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number); + setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); } else { // Combinations of function, class, enum and module - members = emptySymbols; - callSignatures = emptyArray; - constructSignatures = emptyArray; + let members = emptySymbols; + let constructSignatures: Signature[] = emptyArray; if (symbol.flags & SymbolFlags.HasExports) { members = getExportsOfSymbol(symbol); } - if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { - callSignatures = getSignaturesOfSymbol(symbol); - } if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); @@ -3651,10 +3643,16 @@ namespace ts { addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType)); } } - stringIndexType = undefined; - numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; + const numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; + setObjectTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexType); + // We resolve the members before computing the signatures because a signature may use + // typeof with a qualified name expression that circularly references the type we are + // in the process of resolving (see issue #6072). The temporarily empty signature list + // will never be observed because a qualified name can't reference signatures. + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { + (type).callSignatures = getSignaturesOfSymbol(symbol); + } } - setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType); } function resolveStructuredTypeMembers(type: ObjectType): ResolvedType { From 3c8ad42a62021a1aa1a76851b059b61f72b17b31 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 13 Dec 2015 18:32:46 -0800 Subject: [PATCH 49/75] Adding regression test --- .../circularTypeofWithFunctionModule.js | 40 +++++++++++++++++++ .../circularTypeofWithFunctionModule.symbols | 27 +++++++++++++ .../circularTypeofWithFunctionModule.types | 27 +++++++++++++ .../circularTypeofWithFunctionModule.ts | 11 +++++ 4 files changed, 105 insertions(+) create mode 100644 tests/baselines/reference/circularTypeofWithFunctionModule.js create mode 100644 tests/baselines/reference/circularTypeofWithFunctionModule.symbols create mode 100644 tests/baselines/reference/circularTypeofWithFunctionModule.types create mode 100644 tests/cases/compiler/circularTypeofWithFunctionModule.ts diff --git a/tests/baselines/reference/circularTypeofWithFunctionModule.js b/tests/baselines/reference/circularTypeofWithFunctionModule.js new file mode 100644 index 00000000000..6ce1dd62fc5 --- /dev/null +++ b/tests/baselines/reference/circularTypeofWithFunctionModule.js @@ -0,0 +1,40 @@ +//// [circularTypeofWithFunctionModule.ts] +// Repro from #6072 + +class Foo {} + +function maker (value: string): typeof maker.Bar { + return maker.Bar; +} + +namespace maker { + export class Bar extends Foo {} +} + + +//// [circularTypeofWithFunctionModule.js] +// Repro from #6072 +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var Foo = (function () { + function Foo() { + } + return Foo; +}()); +function maker(value) { + return maker.Bar; +} +var maker; +(function (maker) { + var Bar = (function (_super) { + __extends(Bar, _super); + function Bar() { + _super.apply(this, arguments); + } + return Bar; + }(Foo)); + maker.Bar = Bar; +})(maker || (maker = {})); diff --git a/tests/baselines/reference/circularTypeofWithFunctionModule.symbols b/tests/baselines/reference/circularTypeofWithFunctionModule.symbols new file mode 100644 index 00000000000..19dde10852f --- /dev/null +++ b/tests/baselines/reference/circularTypeofWithFunctionModule.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/circularTypeofWithFunctionModule.ts === +// Repro from #6072 + +class Foo {} +>Foo : Symbol(Foo, Decl(circularTypeofWithFunctionModule.ts, 0, 0)) + +function maker (value: string): typeof maker.Bar { +>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1)) +>value : Symbol(value, Decl(circularTypeofWithFunctionModule.ts, 4, 16)) +>maker.Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17)) +>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1)) +>Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17)) + + return maker.Bar; +>maker.Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17)) +>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1)) +>Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17)) +} + +namespace maker { +>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1)) + + export class Bar extends Foo {} +>Bar : Symbol(Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17)) +>Foo : Symbol(Foo, Decl(circularTypeofWithFunctionModule.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/circularTypeofWithFunctionModule.types b/tests/baselines/reference/circularTypeofWithFunctionModule.types new file mode 100644 index 00000000000..f1c2431bfde --- /dev/null +++ b/tests/baselines/reference/circularTypeofWithFunctionModule.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/circularTypeofWithFunctionModule.ts === +// Repro from #6072 + +class Foo {} +>Foo : Foo + +function maker (value: string): typeof maker.Bar { +>maker : typeof maker +>value : string +>maker.Bar : typeof maker.Bar +>maker : typeof maker +>Bar : typeof maker.Bar + + return maker.Bar; +>maker.Bar : typeof maker.Bar +>maker : typeof maker +>Bar : typeof maker.Bar +} + +namespace maker { +>maker : typeof maker + + export class Bar extends Foo {} +>Bar : Bar +>Foo : Foo +} + diff --git a/tests/cases/compiler/circularTypeofWithFunctionModule.ts b/tests/cases/compiler/circularTypeofWithFunctionModule.ts new file mode 100644 index 00000000000..b4c9fdb9fd5 --- /dev/null +++ b/tests/cases/compiler/circularTypeofWithFunctionModule.ts @@ -0,0 +1,11 @@ +// Repro from #6072 + +class Foo {} + +function maker (value: string): typeof maker.Bar { + return maker.Bar; +} + +namespace maker { + export class Bar extends Foo {} +} From 7e71686b1a969b083ee347bdb105fc8a30da6664 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 14 Dec 2015 10:14:35 -0800 Subject: [PATCH 50/75] Fix broken tests --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 4 ++-- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 4 +--- src/services/services.ts | 4 ++-- .../documentHighlightAtParameterPropertyDeclaration2.ts | 2 +- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 9ce8b4f4eda..b63348bfb60 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1444,7 +1444,7 @@ namespace ts { // If this is a property-parameter, then also declare the property symbol into the // containing class. - if (isPropertyParameterDeclaration(node)) { + if (isParameterPropertyDeclaration(node)) { const classDeclaration = node.parent.parent; declareSymbol(classDeclaration.symbol.members, classDeclaration.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a2338c5ba5b..9d14bb39206 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -67,7 +67,7 @@ namespace ts { // The language service will always care about the narrowed type of a symbol, because that is // the type the language says the symbol should have. getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, - getSymbolOfParameterPropertyDeclaration, + getSymbolsOfParameterPropertyDeclaration, getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType, @@ -435,7 +435,7 @@ namespace ts { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): [Symbol, Symbol] { const constructoDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 4c1fb2bb1cd..ad446792f04 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1723,7 +1723,7 @@ namespace ts { getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; getSymbolAtLocation(node: Node): Symbol; - getSymbolOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; + getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; getShorthandAssignmentValueSymbol(location: Node): Symbol; getTypeAtLocation(node: Node): Type; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 566a578cedf..384f27c8868 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2742,9 +2742,7 @@ namespace ts { } } - export function isPropertyParameterDeclaration(node: ParameterDeclaration): boolean { - // If this is a property-parameter, then also declare the property symbol into the - // containing class. + export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean { return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent); } } diff --git a/src/services/services.ts b/src/services/services.ts index 6728c0d5ebc..8e2e4913edd 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5972,8 +5972,8 @@ namespace ts { // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in contructor.locals. // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members if (symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.Parameter && - isPropertyParameterDeclaration(symbol.valueDeclaration)) { - result = result.concat(typeChecker.getSymbolOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); + isParameterPropertyDeclaration(symbol.valueDeclaration)) { + result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); } // If this is a union property, add all the symbols from all its source symbols in all unioned types. diff --git a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts index 2658dd56371..f5d6764205b 100644 --- a/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/documentHighlightAtParameterPropertyDeclaration2.ts @@ -20,5 +20,5 @@ let markers = test.markers() for (let marker of markers) { goTo.position(marker.position); - verify.documentHighlightsAtPositionCount(3, ["file1.ts"]); + verify.documentHighlightsAtPositionCount(2, ["file1.ts"]); } \ No newline at end of file From 37f3ff8d05efc6b3717bc7ead63bc746d509c3ee Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 14 Dec 2015 11:32:06 -0800 Subject: [PATCH 51/75] Check for function flag on class symbol --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7e2bf85c59b..5bfa4744224 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6903,7 +6903,7 @@ namespace ts { .expression as PropertyAccessExpression) // x.prototype .expression; // x const classSymbol = checkExpression(className).symbol; - if (classSymbol && classSymbol.members) { + if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) { return getInferredClassType(classSymbol); } } From c5df5d768e34486f6cff985d9ad521ec906a8e6a Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 14 Dec 2015 12:57:02 -0800 Subject: [PATCH 52/75] Fix linting issue --- Jakefile.js | 3 +- src/services/services.ts | 1073 +++++++++++++++++++------------------- 2 files changed, 538 insertions(+), 538 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index beb16d2886f..91bd805a27b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -924,7 +924,8 @@ function lintFileAsync(options, path, cb) { var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) - .concat(scriptSources); + .concat(scriptSources) + .concat([path.join(servicesDirectory,"services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { diff --git a/src/services/services.ts b/src/services/services.ts index 8e2e4913edd..092f987eb5a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -12,7 +12,7 @@ namespace ts { /** The version of the language service API */ - export let servicesVersion = "0.4" + export const servicesVersion = "0.4"; export interface Node { getSourceFile(): SourceFile; @@ -48,7 +48,7 @@ namespace ts { getConstructSignatures(): Signature[]; getStringIndexType(): Type; getNumberIndexType(): Type; - getBaseTypes(): ObjectType[] + getBaseTypes(): ObjectType[]; } export interface Signature { @@ -97,7 +97,7 @@ namespace ts { dispose?(): void; } - export module ScriptSnapshot { + export namespace ScriptSnapshot { class StringScriptSnapshot implements IScriptSnapshot { constructor(private text: string) { @@ -126,12 +126,12 @@ namespace ts { referencedFiles: FileReference[]; importedFiles: FileReference[]; ambientExternalModules: string[]; - isLibFile: boolean + isLibFile: boolean; } - let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - let emptyArray: any[] = []; + const emptyArray: any[] = []; const jsDocTagNames = [ "augments", @@ -174,7 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - let node = new NodeObject(kind, pos, end); + const node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; @@ -235,8 +235,8 @@ namespace ts { private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - let token = scanner.scan(); - let textPos = scanner.getTextPos(); + const token = scanner.scan(); + const textPos = scanner.getTextPos(); nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this)); pos = textPos; } @@ -244,13 +244,11 @@ namespace ts { } private createSyntaxList(nodes: NodeArray): Node { - let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); + const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); list._children = []; let pos = nodes.pos; - - - for (let node of nodes) { + for (const node of nodes) { if (pos < node.pos) { pos = this.addSyntheticNodes(list._children, pos, node.pos); } @@ -269,14 +267,14 @@ namespace ts { scanner.setText((sourceFile || this.getSourceFile()).text); children = []; let pos = this.pos; - let processNode = (node: Node) => { + const processNode = (node: Node) => { if (pos < node.pos) { pos = this.addSyntheticNodes(children, pos, node.pos); } children.push(node); pos = node.end; }; - let processNodes = (nodes: NodeArray) => { + const processNodes = (nodes: NodeArray) => { if (pos < nodes.pos) { pos = this.addSyntheticNodes(children, pos, nodes.pos); } @@ -308,20 +306,20 @@ namespace ts { } public getFirstToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - let child = children[0]; + const child = children[0]; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); - let child = lastOrUndefined(children); + const child = lastOrUndefined(children); if (!child) { return undefined; } @@ -366,8 +364,8 @@ namespace ts { } function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) { - let documentationComment = []; - let docComments = getJsDocCommentsSeparatedByNewLines(); + const documentationComment = []; + const docComments = getJsDocCommentsSeparatedByNewLines(); ts.forEach(docComments, docComment => { if (documentationComment.length) { documentationComment.push(lineBreakPart()); @@ -378,22 +376,22 @@ namespace ts { return documentationComment; function getJsDocCommentsSeparatedByNewLines() { - let paramTag = "@param"; - let jsDocCommentParts: SymbolDisplayPart[] = []; + const paramTag = "@param"; + const jsDocCommentParts: SymbolDisplayPart[] = []; ts.forEach(declarations, (declaration, indexOfDeclaration) => { // Make sure we are collecting doc comment from declaration once, // In case of union property there might be same declaration multiple times // which only varies in type parameter - // Eg. let a: Array | Array; a.length + // Eg. const a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array if (indexOf(declarations, declaration) === indexOfDeclaration) { - let sourceFileOfDeclaration = getSourceFileOfNode(declaration); + const sourceFileOfDeclaration = getSourceFileOfNode(declaration); // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) { ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedParamJsDocComment) { addRange(jsDocCommentParts, cleanedParamJsDocComment); } @@ -413,7 +411,7 @@ namespace ts { // Get the cleaned js doc comment text from the declaration ts.forEach(getJsDocCommentTextRange( declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedJsDocComment) { addRange(jsDocCommentParts, cleanedJsDocComment); } @@ -439,7 +437,7 @@ namespace ts { } for (; pos < end; pos++) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (!isWhiteSpace(ch) || isLineBreak(ch)) { // Either found lineBreak or non whiteSpace return pos; @@ -480,7 +478,7 @@ namespace ts { function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let spacesToRemoveAfterAsterisk: number; - let docComments: SymbolDisplayPart[] = []; + const docComments: SymbolDisplayPart[] = []; let blankLineCount = 0; let isInParamTag = false; @@ -491,7 +489,7 @@ namespace ts { // If the comment starts with '*' consume the spaces on this line if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - let lineStartPos = pos + 1; + const lineStartPos = pos + 1; pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); // Set the spaces to remove after asterisk as margin if not already set @@ -505,7 +503,7 @@ namespace ts { // Analyse text on this line while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - let ch = sourceFile.text.charAt(pos); + const ch = sourceFile.text.charAt(pos); if (ch === "@") { // If it is @param tag if (isParamTag(pos, end, sourceFile)) { @@ -544,7 +542,7 @@ namespace ts { function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let paramHelpStringMargin: number; - let paramDocComments: SymbolDisplayPart[] = []; + const paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { let blankLineCount = 0; @@ -559,7 +557,7 @@ namespace ts { if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; for (let curlies = 1; pos < end; pos++) { - let charCode = sourceFile.text.charCodeAt(pos); + const charCode = sourceFile.text.charCodeAt(pos); // { character means we need to find another } to match the found one if (charCode === CharacterCodes.openBrace) { @@ -603,9 +601,9 @@ namespace ts { } let paramHelpString = ""; - let firstLineParamHelpStringPos = pos; + const firstLineParamHelpStringPos = pos; while (pos < end) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { @@ -674,15 +672,15 @@ namespace ts { } // Now consume white spaces max - let startOfLinePos = pos; + const startOfLinePos = pos; pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); if (pos >= end) { return; } - let consumedSpaces = pos - startOfLinePos; + const consumedSpaces = pos - startOfLinePos; if (consumedSpaces < paramHelpStringMargin) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (ch === CharacterCodes.asterisk) { // Consume more spaces after asterisk pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); @@ -815,7 +813,7 @@ namespace ts { private namedDeclarations: Map; constructor(kind: SyntaxKind, pos: number, end: number) { - super(kind, pos, end) + super(kind, pos, end); } public update(newText: string, textChangeRange: TextChangeRange): SourceFile { @@ -843,16 +841,16 @@ namespace ts { } private computeNamedDeclarations(): Map { - let result: Map = {}; + const result: Map = {}; forEachChild(this, visit); return result; function addDeclaration(declaration: Declaration) { - let name = getDeclarationName(declaration); + const name = getDeclarationName(declaration); if (name) { - let declarations = getDeclarations(name); + const declarations = getDeclarations(name); declarations.push(declaration); } } @@ -863,13 +861,13 @@ namespace ts { function getDeclarationName(declaration: Declaration) { if (declaration.name) { - let result = getTextOfIdentifierOrLiteral(declaration.name); + const result = getTextOfIdentifierOrLiteral(declaration.name); if (result !== undefined) { return result; } if (declaration.name.kind === SyntaxKind.ComputedPropertyName) { - let expr = (declaration.name).expression; + const expr = (declaration.name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } @@ -899,12 +897,12 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - let functionDeclaration = node; - let declarationName = getDeclarationName(functionDeclaration); + const functionDeclaration = node; + const declarationName = getDeclarationName(functionDeclaration); if (declarationName) { - let declarations = getDeclarations(declarationName); - let lastDeclaration = lastOrUndefined(declarations); + const declarations = getDeclarations(declarationName); + const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { @@ -980,7 +978,7 @@ namespace ts { break; case SyntaxKind.ImportDeclaration: - let importClause = (node).importClause; + const importClause = (node).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -1113,8 +1111,8 @@ namespace ts { } export interface Classifications { - spans: number[], - endOfLineState: EndOfLineState + spans: number[]; + endOfLineState: EndOfLineState; } export interface ClassifiedSpan { @@ -1171,7 +1169,7 @@ namespace ts { highlightSpans: HighlightSpan[]; } - export module HighlightSpanKind { + export namespace HighlightSpanKind { export const none = "none"; export const definition = "definition"; export const reference = "reference"; @@ -1220,7 +1218,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } export interface DefinitionInfo { @@ -1500,7 +1498,7 @@ namespace ts { } // TODO: move these to enums - export module ScriptElementKind { + export namespace ScriptElementKind { export const unknown = ""; export const warning = "warning"; @@ -1529,7 +1527,7 @@ namespace ts { export const enumElement = "enum"; // Inside module and script only - // let v = .. + // const v = .. export const variableElement = "var"; // Inside function @@ -1581,7 +1579,7 @@ namespace ts { export const letElement = "let"; } - export module ScriptElementKindModifier { + export namespace ScriptElementKindModifier { export const none = ""; export const publicMemberModifier = "public"; export const privateMemberModifier = "private"; @@ -1723,8 +1721,8 @@ namespace ts { this.fileNameToEntry = createFileMap(); // Initialize the list with the root file names - let rootFileNames = host.getScriptFileNames(); - for (let fileName of rootFileNames) { + const rootFileNames = host.getScriptFileNames(); + for (const fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } @@ -1738,7 +1736,7 @@ namespace ts { private createEntry(fileName: string, path: Path) { let entry: HostFileInformation; - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, @@ -1760,7 +1758,7 @@ namespace ts { } public getOrCreateEntry(fileName: string): HostFileInformation { - let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName) + const path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName); if (this.contains(path)) { return this.getEntry(path); } @@ -1769,7 +1767,7 @@ namespace ts { } public getRootFileNames(): string[] { - let fileNames: string[] = []; + const fileNames: string[] = []; this.fileNameToEntry.forEachValue((path, value) => { if (value) { @@ -1781,12 +1779,12 @@ namespace ts { } public getVersion(path: Path): string { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.version; } public getScriptSnapshot(path: Path): IScriptSnapshot { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.scriptSnapshot; } } @@ -1803,22 +1801,22 @@ namespace ts { } public getCurrentSourceFile(fileName: string): SourceFile { - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - let version = this.host.getScriptVersion(fileName); + const version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } @@ -1863,7 +1861,7 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1879,21 +1877,22 @@ namespace ts { options.noResolve = true; // if jsx is specified then treat file as .tsx - let inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - let sourceFile = createSourceFile(inputFileName, input, options.target); + const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + const sourceFile = createSourceFile(inputFileName, input, options.target); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } sourceFile.renamedDependencies = transpileOptions.renamedDependencies; - let newLine = getNewLineCharacter(options); + const newLine = getNewLineCharacter(options); // Output let outputText: string; let sourceMapText: string; + // Create a compilerHost object to allow the compiler to read and write files - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined, writeFile: (name, text, writeByteOrderMark) => { if (fileExtensionIs(name, ".map")) { @@ -1914,7 +1913,7 @@ namespace ts { readFile: (fileName): string => "" }; - let program = createProgram([inputFileName], options, compilerHost); + const program = createProgram([inputFileName], options, compilerHost); let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { @@ -1934,22 +1933,22 @@ namespace ts { * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { - let output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); + const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); return output.outputText; } export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { - let text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - let sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); setSourceFileFields(sourceFile, scriptSnapshot, version); // after full parsing we can use table with interned strings as name table sourceFile.nameTable = sourceFile.identifiers; return sourceFile; } - export let disableIncrementalParsing = false; + export const disableIncrementalParsing = false; export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { // If we were given a text change range, and our version or open-ness changed, then @@ -1961,12 +1960,12 @@ namespace ts { let newText: string; // grab the fragment from the beginning of the original text to the beginning of the span - let prefix = textChangeRange.span.start !== 0 + const prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text - let suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; @@ -1976,7 +1975,7 @@ namespace ts { } else { // it was actual edit, fetch the fragment of new text that correspond to new span - let changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1985,7 +1984,7 @@ namespace ts { : (changedText + suffix); } - let newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -2006,7 +2005,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { @@ -2019,15 +2018,15 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - let buckets: Map> = {}; - let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); + const buckets: Map> = {}; + const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyFromCompilationSettings(settings: CompilerOptions): string { return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + +"|" + settings.allowJs; } function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap { - let key = getKeyFromCompilationSettings(settings); + const key = getKeyFromCompilationSettings(settings); let bucket = lookUp(buckets, key); if (!bucket && createIfMissing) { buckets[key] = bucket = createFileMap(); @@ -2036,9 +2035,9 @@ namespace ts { } function reportStats() { - let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => { - let entries = lookUp(buckets, name); - let sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; + const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => { + const entries = lookUp(buckets, name); + const sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; entries.forEachValue((key, entry) => { sourceFiles.push({ name: key, @@ -2052,15 +2051,15 @@ namespace ts { sourceFiles }; }); - return JSON.stringify(bucketInfoArray, null, 2); + return JSON.stringify(bucketInfoArray, undefined, 2); } function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); } function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); } function acquireOrUpdateDocument( @@ -2070,14 +2069,14 @@ namespace ts { version: string, acquiring: boolean): SourceFile { - let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); let entry = bucket.get(path); if (!entry) { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); entry = { sourceFile: sourceFile, @@ -2109,12 +2108,12 @@ namespace ts { } function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void { - let bucket = getBucketForCompilationSettings(compilationSettings, false); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/false); Debug.assert(bucket !== undefined); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); - let entry = bucket.get(path); + const entry = bucket.get(path); entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); @@ -2132,19 +2131,19 @@ namespace ts { } export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { - let referencedFiles: FileReference[] = []; - let importedFiles: FileReference[] = []; + const referencedFiles: FileReference[] = []; + const importedFiles: FileReference[] = []; let ambientExternalModules: string[]; let isNoDefaultLib = false; function processTripleSlashDirectives(): void { - let commentRanges = getLeadingCommentRanges(sourceText, 0); + const commentRanges = getLeadingCommentRanges(sourceText, 0); forEach(commentRanges, commentRange => { - let comment = sourceText.substring(commentRange.pos, commentRange.end); - let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); + const comment = sourceText.substring(commentRange.pos, commentRange.end); + const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; - let fileReference = referencePathMatchResult.fileReference; + const fileReference = referencePathMatchResult.fileReference; if (fileReference) { referencedFiles.push(fileReference); } @@ -2160,8 +2159,8 @@ namespace ts { } function recordModuleName() { - let importPath = scanner.getTokenValue(); - let pos = scanner.getTokenPos(); + const importPath = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); importedFiles.push({ fileName: importPath, pos: pos, @@ -2213,7 +2212,7 @@ namespace ts { } } else if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2311,7 +2310,7 @@ namespace ts { if (token === SyntaxKind.Identifier || isKeyword(token)) { token = scanner.scan(); if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2410,7 +2409,7 @@ namespace ts { if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -2550,8 +2549,8 @@ namespace ts { return true; } else if (position === comment.end) { - let text = sourceFile.text; - let width = comment.end - comment.pos; + const text = sourceFile.text; + const width = comment.end - comment.pos; // is single line comment or just /* if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { return true; @@ -2583,7 +2582,7 @@ namespace ts { } // A cache of completion entries for keywords, these do not change between sessions - let keywordCompletions: CompletionEntry[] = []; + const keywordCompletions: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { keywordCompletions.push({ name: tokenToString(i), @@ -2673,15 +2672,15 @@ namespace ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { - let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); + const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); let ruleProvider: formatting.RulesProvider; let program: Program; let lastProjectVersion: string; - let useCaseSensitivefileNames = false; - let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + const useCaseSensitivefileNames = false; + const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - let currentDirectory = host.getCurrentDirectory(); + const currentDirectory = host.getCurrentDirectory(); // Check if the localized messages json is set, otherwise query the host for it if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); @@ -2693,10 +2692,10 @@ namespace ts { } } - let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); function getValidSourceFile(fileName: string): SourceFile { - let sourceFile = program.getSourceFile(fileName); + const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); } @@ -2716,7 +2715,7 @@ namespace ts { function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { - let hostProjectVersion = host.getProjectVersion(); + const hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion) { return; @@ -2740,17 +2739,17 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - let oldSettings = program && program.getCompilerOptions(); - let newSettings = hostCache.compilationSettings(); - let changesInCompilationSettingsAffectSyntax = oldSettings && + const oldSettings = program && program.getCompilerOptions(); + const newSettings = hostCache.compilationSettings(); + const changesInCompilationSettingsAffectSyntax = oldSettings && (oldSettings.target !== newSettings.target || oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || + oldSettings.jsx !== newSettings.jsx || oldSettings.allowJs !== newSettings.allowJs); // Now create a new compiler - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, getCancellationToken: () => cancellationToken, getCanonicalFileName, @@ -2766,22 +2765,22 @@ namespace ts { }, readFile: (fileName): string => { // stub missing host functionality - let entry = hostCache.getOrCreateEntry(fileName); + const entry = hostCache.getOrCreateEntry(fileName); return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); } }; if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile) + compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); } - let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); // Release any files we have acquired in the old program but are // not part of the new program. if (program) { - let oldSourceFiles = program.getSourceFiles(); - for (let oldSourceFile of oldSourceFiles) { + const oldSourceFiles = program.getSourceFiles(); + for (const oldSourceFile of oldSourceFiles) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings); } @@ -2804,7 +2803,7 @@ namespace ts { // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. - let hostFileInformation = hostCache.getOrCreateEntry(fileName); + const hostFileInformation = hostCache.getOrCreateEntry(fileName); if (!hostFileInformation) { return undefined; } @@ -2814,7 +2813,7 @@ namespace ts { // can not be reused. we have to dump all syntax trees and create new ones. if (!changesInCompilationSettingsAffectSyntax) { // Check if the old program had this file already - let oldSourceFile = program && program.getSourceFile(fileName); + const oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to @@ -2851,7 +2850,7 @@ namespace ts { if (!sourceFile) { return false; } - let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + const path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); return sourceFile.version === hostCache.getVersion(path); } @@ -2862,13 +2861,13 @@ namespace ts { } // If number of files in the program do not match, it is not up-to-date - let rootFileNames = hostCache.getRootFileNames(); + const rootFileNames = hostCache.getRootFileNames(); if (program.getSourceFiles().length !== rootFileNames.length) { return false; } // If any file is not up-to-date, then the whole program is not up-to-date - for (let fileName of rootFileNames) { + for (const fileName of rootFileNames) { if (!sourceFileUpToDate(program.getSourceFile(fileName))) { return false; } @@ -2910,18 +2909,18 @@ namespace ts { function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); - let targetSourceFile = getValidSourceFile(fileName); + const targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. - let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics; } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return concatenate(semanticDiagnostics, declarationDiagnostics); } @@ -2937,14 +2936,14 @@ namespace ts { * @return undefined if the name is of external module otherwise a name with striped of any quote */ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, location: Node): string { - let displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); + const displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); if (displayName) { - let firstCharCode = displayName.charCodeAt(0); + const firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there) + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) return undefined; } } @@ -2987,20 +2986,20 @@ namespace ts { } function getCompletionData(fileName: string, position: number) { - let typeChecker = program.getTypeChecker(); - let syntacticStart = new Date().getTime(); - let sourceFile = getValidSourceFile(fileName); - let isJavaScriptFile = isSourceFileJavaScript(sourceFile); + const typeChecker = program.getTypeChecker(); + const syntacticStart = new Date().getTime(); + const sourceFile = getValidSourceFile(fileName); + const isJavaScriptFile = isSourceFileJavaScript(sourceFile); let isJsDocTagName = false; let start = new Date().getTime(); - let currentToken = getTokenAtPosition(sourceFile, position); + const currentToken = getTokenAtPosition(sourceFile, position); log("getCompletionData: Get current token: " + (new Date().getTime() - start)); start = new Date().getTime(); // Completion not allowed inside comments, bail out if this is the case - let insideComment = isInsideComment(sourceFile, currentToken, position); + const insideComment = isInsideComment(sourceFile, currentToken, position); log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { @@ -3014,7 +3013,7 @@ namespace ts { // /** @type {number | string} */ // Completion should work in the brackets let insideJsDocTagExpression = false; - let tag = getJsDocTagAtPosition(sourceFile, position); + const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { isJsDocTagName = true; @@ -3024,7 +3023,7 @@ namespace ts { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocReturnTag: - let tagWithExpression = tag; + const tagWithExpression = tag; if (tagWithExpression.typeExpression) { insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; } @@ -3045,7 +3044,7 @@ namespace ts { } start = new Date().getTime(); - let previousToken = findPrecedingToken(position, sourceFile); + const previousToken = findPrecedingToken(position, sourceFile); log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -3055,7 +3054,7 @@ namespace ts { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { - let start = new Date().getTime(); + const start = new Date().getTime(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start)); } @@ -3076,7 +3075,7 @@ namespace ts { return undefined; } - let { parent, kind } = contextToken; + const { parent, kind } = contextToken; if (kind === SyntaxKind.DotToken) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { node = (contextToken.parent).expression; @@ -3103,7 +3102,7 @@ namespace ts { } } - let semanticStart = new Date().getTime(); + const semanticStart = new Date().getTime(); let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; let symbols: Symbol[] = []; @@ -3112,7 +3111,7 @@ namespace ts { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - let tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value))); } @@ -3123,7 +3122,7 @@ namespace ts { isNewIdentifierLocation = false; } else if (isStartingCloseTag) { - let tagName = (contextToken.parent.parent).openingElement.tagName; + const tagName = (contextToken.parent.parent).openingElement.tagName; symbols = [typeChecker.getSymbolAtLocation(tagName)]; isMemberCompletion = true; @@ -3157,7 +3156,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members - let exportedSymbols = typeChecker.getExportsOfModule(symbol); + const exportedSymbols = typeChecker.getExportsOfModule(symbol); forEach(exportedSymbols, symbol => { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); @@ -3166,14 +3165,14 @@ namespace ts { } } - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); addTypeProperties(type); } function addTypeProperties(type: Type) { if (type) { // Filter private properties - for (let symbol of type.getApparentProperties()) { + for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } @@ -3185,8 +3184,8 @@ namespace ts { // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - let unionType = type; - for (let elementType of unionType.types) { + const unionType = type; + for (const elementType of unionType.types) { addTypeProperties(elementType); } } @@ -3256,14 +3255,14 @@ namespace ts { // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - let adjustedPosition = previousToken !== contextToken ? + const adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; - let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context - let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); return true; @@ -3282,8 +3281,8 @@ namespace ts { } function isCompletionListBlocker(contextToken: Node): boolean { - let start = new Date().getTime(); - let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + const start = new Date().getTime(); + const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken); @@ -3310,27 +3309,27 @@ namespace ts { function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { - let containingNodeKind = previousToken.parent.kind; + const containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.CallExpression // func( a, | || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ || containingNodeKind === SyntaxKind.NewExpression // new C(a, | || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === SyntaxKind.BinaryExpression // let x = (a, | + || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list| case SyntaxKind.OpenParenToken: return containingNodeKind === SyntaxKind.CallExpression // func( | || containingNodeKind === SyntaxKind.Constructor // constructor( | || containingNodeKind === SyntaxKind.NewExpression // new C(a| - || containingNodeKind === SyntaxKind.ParenthesizedExpression // let x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ case SyntaxKind.OpenBracketToken: return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === SyntaxKind.ComputedPropertyName // [ | /* this can become an index signature */ + || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ case SyntaxKind.ModuleKeyword: // module | case SyntaxKind.NamespaceKeyword: // namespace | @@ -3343,7 +3342,7 @@ namespace ts { return containingNodeKind === SyntaxKind.ClassDeclaration; // class A{ | case SyntaxKind.EqualsToken: - return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a| + return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| case SyntaxKind.TemplateHead: @@ -3375,8 +3374,8 @@ namespace ts { || contextToken.kind === SyntaxKind.StringLiteralType || contextToken.kind === SyntaxKind.RegularExpressionLiteral || isTemplateLiteralKind(contextToken.kind)) { - let start = contextToken.getStart(); - let end = contextToken.getEnd(); + const start = contextToken.getStart(); + const end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. @@ -3420,7 +3419,7 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); if (isVariableLike(rootDeclaration)) { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -3431,7 +3430,7 @@ namespace ts { } } else { - Debug.fail("Root declaration is not variable-like.") + Debug.fail("Root declaration is not variable-like."); } } else { @@ -3442,7 +3441,7 @@ namespace ts { return false; } - let typeMembers = typeChecker.getPropertiesOfType(typeForObject); + const typeMembers = typeChecker.getPropertiesOfType(typeForObject); if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, existingMembers); @@ -3466,11 +3465,11 @@ namespace ts { * @returns true if 'symbols' was successfully populated; false otherwise. */ function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { - let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? SyntaxKind.ImportDeclaration : SyntaxKind.ExportDeclaration; - let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); - let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + const importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + const moduleSpecifier = importOrExportDeclaration.moduleSpecifier; if (!moduleSpecifier) { return false; @@ -3480,7 +3479,7 @@ namespace ts { isNewIdentifierLocation = false; let exports: Symbol[]; - let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); if (moduleSpecifierSymbol) { exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } @@ -3497,9 +3496,9 @@ namespace ts { function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { if (contextToken) { switch (contextToken.kind) { - case SyntaxKind.OpenBraceToken: // let x = { | - case SyntaxKind.CommaToken: // let x = { a: 0, | - let parent = contextToken.parent; + case SyntaxKind.OpenBraceToken: // const x = { | + case SyntaxKind.CommaToken: // const x = { a: 0, | + const parent = contextToken.parent; if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { return parent; } @@ -3532,8 +3531,8 @@ namespace ts { function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { - let parent = contextToken.parent; - switch(contextToken.kind) { + const parent = contextToken.parent; + switch (contextToken.kind) { case SyntaxKind.LessThanSlashToken: case SyntaxKind.SlashToken: case SyntaxKind.Identifier: @@ -3596,7 +3595,7 @@ namespace ts { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - let containingNodeKind = contextToken.parent.kind; + const containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -3626,13 +3625,13 @@ namespace ts { case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { | containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface a { | - containingNodeKind === SyntaxKind.TypeLiteral; // let x : { | + containingNodeKind === SyntaxKind.TypeLiteral; // const x : { | case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && contextToken.parent && contextToken.parent.parent && (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // let x : { a; | + contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -3699,7 +3698,7 @@ namespace ts { function isDotOfNumericLiteral(contextToken: Node): boolean { if (contextToken.kind === SyntaxKind.NumericLiteral) { - let text = contextToken.getFullText(); + const text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3716,15 +3715,15 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - let exisingImportsOrExports: Map = {}; + const exisingImportsOrExports: Map = {}; - for (let element of namedImportsOrExports) { + for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out if (element.getStart() <= position && position <= element.getEnd()) { continue; } - let name = element.propertyName || element.name; + const name = element.propertyName || element.name; exisingImportsOrExports[name.text] = true; } @@ -3746,8 +3745,8 @@ namespace ts { return contextualMemberSymbols; } - let existingMemberNames: Map = {}; - for (let m of existingMembers) { + const existingMemberNames: Map = {}; + for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment && @@ -3766,7 +3765,7 @@ namespace ts { if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).text + existingName = ((m).propertyName).text; } } else { @@ -3789,8 +3788,8 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - let seenNames: Map = {}; - for (let attr of attributes) { + const seenNames: Map = {}; + for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { continue; @@ -3809,21 +3808,21 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (!completionData) { return undefined; } - let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; + const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let entries: CompletionEntry[] = []; + const entries: CompletionEntry[] = []; if (isRightOfDot && isSourceFileJavaScript(sourceFile)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); @@ -3845,16 +3844,16 @@ namespace ts { return { isMemberCompletion, isNewIdentifierLocation, entries }; function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map): CompletionEntry[] { - let entries: CompletionEntry[] = []; - let target = program.getCompilerOptions().target; + const entries: CompletionEntry[] = []; + const target = program.getCompilerOptions().target; - let nameTable = getNameTable(sourceFile); - for (let name in nameTable) { + const nameTable = getNameTable(sourceFile); + for (const name in nameTable) { if (!uniqueNames[name]) { uniqueNames[name] = name; - let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true); + const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true); if (displayName) { - let entry = { + const entry = { name: displayName, kind: ScriptElementKind.warning, kindModifiers: "", @@ -3875,7 +3874,7 @@ namespace ts { kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - } + }; })); } @@ -3883,7 +3882,7 @@ namespace ts { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true, location); + const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location); if (!displayName) { return undefined; } @@ -3905,13 +3904,13 @@ namespace ts { } function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map { - let start = new Date().getTime(); - let uniqueNames: Map = {}; + const start = new Date().getTime(); + const uniqueNames: Map = {}; if (symbols) { - for (let symbol of symbols) { - let entry = createCompletionEntry(symbol, location); + for (const symbol of symbols) { + const entry = createCompletionEntry(symbol, location); if (entry) { - let id = escapeIdentifier(entry.name); + const id = escapeIdentifier(entry.name); if (!lookUp(uniqueNames, id)) { entries.push(entry); uniqueNames[id] = id; @@ -3929,19 +3928,19 @@ namespace ts { synchronizeHostData(); // Compute all the completion symbols again. - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (completionData) { - let { symbols, location } = completionData; + const { symbols, location } = completionData; // Find the symbol with the matching entry name. - let target = program.getCompilerOptions().target; + const target = program.getCompilerOptions().target; // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false, location) === entryName ? s : undefined); + const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined); if (symbol) { - let { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); + const { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); return { name: entryName, kindModifiers: getSymbolModifiers(symbol), @@ -3953,7 +3952,7 @@ namespace ts { } // Didn't find a symbol with this name. See if we can find a keyword instead. - let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); + const keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); if (keywordCompletion) { return { name: entryName, @@ -3969,7 +3968,7 @@ namespace ts { // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(symbol: Symbol, location: Node): string { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; @@ -3978,7 +3977,7 @@ namespace ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); + const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -3990,7 +3989,7 @@ namespace ts { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; @@ -4019,8 +4018,8 @@ namespace ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { - let rootSymbolFlags = rootSymbol.getFlags(); + const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + const rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { return ScriptElementKind.memberVariableElement; } @@ -4028,8 +4027,8 @@ namespace ts { }); if (!unionPropertyKind) { // If this was union of all methods, - //make sure it has call signatures before we can label it as method - let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + // make sure it has call signatures before we can label it as method + const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -4053,11 +4052,11 @@ namespace ts { function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning = getMeaningFromLocation(location)) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let displayParts: SymbolDisplayPart[] = []; + const displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[]; - let symbolFlags = symbol.flags; + const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; let type: Type; @@ -4073,7 +4072,7 @@ namespace ts { type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - let right = (location.parent).name; + const right = (location.parent).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -4090,15 +4089,15 @@ namespace ts { } if (callExpression) { - let candidateSignatures: Signature[] = []; + const candidateSignatures: Signature[] = []; signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); if (!signature && candidateSignatures.length) { // Use the first candidate: signature = candidateSignatures[0]; } - let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; - let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; + const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -4156,8 +4155,8 @@ namespace ts { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - let functionDeclaration = location.parent; - let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + const functionDeclaration = location.parent; + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4226,8 +4225,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - let declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); - let isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); addFullSymbolName(symbol); @@ -4279,9 +4278,9 @@ namespace ts { } if (symbolFlags & SymbolFlags.EnumMember) { addPrefixForAnyFunctionOrVar(symbol, "enum member"); - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { - let constantValue = typeChecker.getConstantValue(declaration); + const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4297,7 +4296,7 @@ namespace ts { addFullSymbolName(symbol); ts.forEach(symbol.declarations, declaration => { if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { - let importEqualsDeclaration = declaration; + const importEqualsDeclaration = declaration; if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4308,7 +4307,7 @@ namespace ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4332,7 +4331,7 @@ namespace ts { displayParts.push(spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4347,7 +4346,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - let allSignatures = type.getCallSignatures(); + const allSignatures = type.getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } @@ -4370,7 +4369,7 @@ namespace ts { } function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) { - let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); addRange(displayParts, fullSymbolDisplayParts); } @@ -4416,7 +4415,7 @@ namespace ts { } function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4426,8 +4425,8 @@ namespace ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -4436,8 +4435,8 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const typeChecker = program.getTypeChecker(); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { // Try getting just type at this position and show @@ -4449,7 +4448,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -4464,7 +4463,7 @@ namespace ts { return undefined; } - let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); + const displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), @@ -4486,13 +4485,13 @@ namespace ts { } function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { - let typeChecker = program.getTypeChecker(); - let result: DefinitionInfo[] = []; - let declarations = symbol.getDeclarations(); - let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - let symbolKind = getSymbolKind(symbol, node); - let containerSymbol = symbol.parent; - let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + const typeChecker = program.getTypeChecker(); + const result: DefinitionInfo[] = []; + const declarations = symbol.getDeclarations(); + const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol + const symbolKind = getSymbolKind(symbol, node); + const containerSymbol = symbol.parent; + const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -4510,7 +4509,7 @@ namespace ts { if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { // Find the first class-like declaration and try to get the construct signature. - for (let declaration of symbol.getDeclarations()) { + for (const declaration of symbol.getDeclarations()) { if (isClassLike(declaration)) { return tryAddSignature(declaration.members, /*selectConstructors*/ true, @@ -4535,7 +4534,7 @@ namespace ts { } function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - let declarations: Declaration[] = []; + const declarations: Declaration[] = []; let definition: Declaration; forEach(signatureDeclarations, d => { @@ -4563,24 +4562,24 @@ namespace ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } // Labels if (isJumpStatementTarget(node)) { - let labelName = (node).text; - let label = getTargetLabel((node.parent), (node).text); + const labelName = (node).text; + const label = getTargetLabel((node.parent), (node).text); return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments - let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); + const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); if (comment) { - let referenceFile = tryResolveScriptReference(program, sourceFile, comment); + const referenceFile = tryResolveScriptReference(program, sourceFile, comment); if (referenceFile) { return [{ fileName: referenceFile.fileName, @@ -4594,7 +4593,7 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, @@ -4608,7 +4607,7 @@ namespace ts { // import {A, B} from "mod"; // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { symbol = typeChecker.getAliasedSymbol(symbol); } @@ -4620,15 +4619,15 @@ namespace ts { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); if (!shorthandSymbol) { return []; } - let shorthandDeclarations = shorthandSymbol.getDeclarations(); - let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); - let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + const shorthandDeclarations = shorthandSymbol.getDeclarations(); + const shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); + const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); + const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -4640,27 +4639,27 @@ namespace ts { function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; } - let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); if (!type) { return undefined; } if (type.flags & TypeFlags.Union) { - let result: DefinitionInfo[] = []; + const result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); @@ -4680,7 +4679,7 @@ namespace ts { let results = getOccurrencesAtPositionCore(fileName, position); if (results) { - let sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); + const sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); // Get occurrences only supports reporting occurrences for the file queried. So // filter down to that list. @@ -4694,10 +4693,10 @@ namespace ts { synchronizeHostData(); filesToSearch = map(filesToSearch, normalizeSlashes); - let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); - let sourceFile = getValidSourceFile(fileName); + const sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -4705,8 +4704,8 @@ namespace ts { return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); function getHighlightSpanForNode(node: Node): HighlightSpan { - let start = node.getStart(); - let end = node.getEnd(); + const start = node.getStart(); + const end = node.getEnd(); return { fileName: sourceFile.fileName, @@ -4723,7 +4722,7 @@ namespace ts { isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - let referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); return convertReferencedSymbols(referencedSymbols); } @@ -4734,11 +4733,11 @@ namespace ts { return undefined; } - let fileNameToDocumentHighlights: Map = {}; - let result: DocumentHighlights[] = []; - for (let referencedSymbol of referencedSymbols) { - for (let referenceEntry of referencedSymbol.references) { - let fileName = referenceEntry.fileName; + const fileNameToDocumentHighlights: Map = {}; + const result: DocumentHighlights[] = []; + for (const referencedSymbol of referencedSymbols) { + for (const referenceEntry of referencedSymbol.references) { + const fileName = referenceEntry.fileName; let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName); if (!documentHighlights) { documentHighlights = { fileName, highlightSpans: [] }; @@ -4759,9 +4758,9 @@ namespace ts { } function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] { - let fileName = sourceFile.fileName; + const fileName = sourceFile.fileName; - let highlightSpans = getHighlightSpans(node); + const highlightSpans = getHighlightSpans(node); if (!highlightSpans || highlightSpans.length === 0) { return undefined; } @@ -4865,7 +4864,7 @@ namespace ts { * into function boundaries and try-blocks with catch-clauses. */ function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] { - let statementAccumulator: ThrowStatement[] = [] + const statementAccumulator: ThrowStatement[] = []; aggregate(node); return statementAccumulator; @@ -4874,7 +4873,7 @@ namespace ts { statementAccumulator.push(node); } else if (node.kind === SyntaxKind.TryStatement) { - let tryStatement = node; + const tryStatement = node; if (tryStatement.catchClause) { aggregate(tryStatement.catchClause); @@ -4905,7 +4904,7 @@ namespace ts { let child: Node = throwStatement; while (child.parent) { - let parent = child.parent; + const parent = child.parent; if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; @@ -4914,7 +4913,7 @@ namespace ts { // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. if (parent.kind === SyntaxKind.TryStatement) { - let tryStatement = parent; + const tryStatement = parent; if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; @@ -4928,7 +4927,7 @@ namespace ts { } function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] { - let statementAccumulator: BreakOrContinueStatement[] = [] + const statementAccumulator: BreakOrContinueStatement[] = []; aggregate(node); return statementAccumulator; @@ -4944,7 +4943,7 @@ namespace ts { } function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { - let actualOwner = getBreakOrContinueOwner(statement); + const actualOwner = getBreakOrContinueOwner(statement); return actualOwner && actualOwner === owner; } @@ -4979,7 +4978,7 @@ namespace ts { } function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] { - let container = declaration.parent; + const container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { @@ -5009,8 +5008,8 @@ namespace ts { return undefined; } - let keywords: Node[] = []; - let modifierFlag: NodeFlags = getFlagFromModifier(modifier); + const keywords: Node[] = []; + const modifierFlag: NodeFlags = getFlagFromModifier(modifier); let nodes: Node[]; switch (container.kind) { @@ -5035,7 +5034,7 @@ namespace ts { // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - let constructor = forEach((container).members, member => { + const constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -5048,7 +5047,7 @@ namespace ts { } break; default: - Debug.fail("Invalid container kind.") + Debug.fail("Invalid container kind."); } forEach(nodes, node => { @@ -5091,7 +5090,7 @@ namespace ts { } function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor); tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor); @@ -5099,7 +5098,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void { - let accessor = getDeclarationOfKind(accessorSymbol, accessorKind); + const accessor = getDeclarationOfKind(accessorSymbol, accessorKind); if (accessor) { forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword)); @@ -5108,9 +5107,9 @@ namespace ts { } function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] { - let declarations = constructorDeclaration.symbol.getDeclarations() + const declarations = constructorDeclaration.symbol.getDeclarations(); - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(declarations, declaration => { forEach(declaration.getChildren(), token => { @@ -5122,12 +5121,12 @@ namespace ts { } function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { - let loopTokens = loopNode.getChildren(); + const loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { @@ -5137,7 +5136,7 @@ namespace ts { } } - let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { @@ -5149,7 +5148,7 @@ namespace ts { } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { - let owner = getBreakOrContinueOwner(breakOrContinueStatement); + const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { @@ -5158,7 +5157,7 @@ namespace ts { case SyntaxKind.ForOfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner) + return getLoopBreakContinueOccurrences(owner); case SyntaxKind.SwitchStatement: return getSwitchCaseDefaultOccurrences(owner); @@ -5169,7 +5168,7 @@ namespace ts { } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -5177,7 +5176,7 @@ namespace ts { forEach(switchStatement.caseBlock.clauses, clause => { pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { @@ -5190,7 +5189,7 @@ namespace ts { } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); @@ -5199,7 +5198,7 @@ namespace ts { } if (tryStatement.finallyBlock) { - let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } @@ -5207,13 +5206,13 @@ namespace ts { } function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] { - let owner = getThrowStatementOwner(throwStatement); + const owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(aggregateOwnedThrowStatements(owner), throwStatement => { pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword); @@ -5231,14 +5230,14 @@ namespace ts { } function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] { - let func = getContainingFunction(returnStatement); + const func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } - let keywords: Node[] = [] + const keywords: Node[] = []; forEachReturnStatement(func.body, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -5252,7 +5251,7 @@ namespace ts { } function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (ifStatement.parent).elseStatement === ifStatement) { @@ -5261,7 +5260,7 @@ namespace ts { // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (ifStatement) { - let children = ifStatement.getChildren(); + const children = ifStatement.getChildren(); pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. @@ -5272,20 +5271,20 @@ namespace ts { } if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) { - break + break; } ifStatement = ifStatement.elseStatement; } - let result: HighlightSpan[] = []; + const result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { - let elseKeyword = keywords[i]; - let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + const elseKeyword = keywords[i]; + const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. let shouldCombindElseAndIf = true; @@ -5328,9 +5327,9 @@ namespace ts { return undefined; } - let result: ReferenceEntry[] = []; - for (let entry of documentHighlights) { - for (let highlightSpan of entry.highlightSpans) { + const result: ReferenceEntry[] = []; + for (const entry of documentHighlights) { + for (const highlightSpan of entry.highlightSpans) { result.push({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -5348,9 +5347,9 @@ namespace ts { return undefined; } - let referenceEntries: ReferenceEntry[] = []; + const referenceEntries: ReferenceEntry[] = []; - for (let referenceSymbol of referenceSymbols) { + for (const referenceSymbol of referenceSymbols) { addRange(referenceEntries, referenceSymbol.references); } @@ -5358,17 +5357,17 @@ namespace ts { } function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - let referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + const referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number): ReferencedSymbol[]{ - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + function findReferences(fileName: string, position: number): ReferencedSymbol[] { + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); @@ -5377,17 +5376,17 @@ namespace ts { function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } if (node.kind !== SyntaxKind.Identifier && // TODO (drosen): This should be enabled in a later release - currently breaks rename. - //node.kind !== SyntaxKind.ThisKeyword && - //node.kind !== SyntaxKind.SuperKeyword && + // node.kind !== SyntaxKind.ThisKeyword && + // node.kind !== SyntaxKind.SuperKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -5398,12 +5397,12 @@ namespace ts { } function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - let labelDefinition = getTargetLabel((node.parent), (node).text); + const labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; @@ -5422,7 +5421,7 @@ namespace ts { return getReferencesForSuperKeyword(node); } - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -5430,7 +5429,7 @@ namespace ts { return undefined; } - let declarations = symbol.declarations; + const declarations = symbol.declarations; // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!declarations || !declarations.length) { @@ -5440,29 +5439,29 @@ namespace ts { let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references - let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); + const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - let declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). - let scope = getSymbolScope(symbol); + const scope = getSymbolScope(symbol); // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - let symbolToIndex: number[] = []; + const symbolToIndex: number[] = []; if (scope) { result = []; getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - let internedName = getInternedName(symbol, node, declarations) - for (let sourceFile of sourceFiles) { + const internedName = getInternedName(symbol, node, declarations); + for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - let nameTable = getNameTable(sourceFile); + const nameTable = getNameTable(sourceFile); if (lookUp(nameTable, internedName)) { result = result || []; @@ -5474,9 +5473,9 @@ namespace ts { return result; function getDefinition(symbol: Symbol): DefinitionInfo { - let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - let name = map(info.displayParts, p => p.text).join(""); - let declarations = symbol.declarations; + const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); + const name = map(info.displayParts, p => p.text).join(""); + const declarations = symbol.declarations; if (!declarations || declarations.length === 0) { return undefined; } @@ -5506,7 +5505,7 @@ namespace ts { // Try to get the local symbol if we're dealing with an 'export default' // since that symbol has the "true" name. - let localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); + const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); symbol = localExportDefaultSymbol || symbol; return stripQuotes(symbol.name); @@ -5523,14 +5522,14 @@ namespace ts { function getSymbolScope(symbol: Symbol): Node { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. - let valueDeclaration = symbol.valueDeclaration; + const valueDeclaration = symbol.valueDeclaration; if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } // If this is private property or method, the scope is the containing class if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { - let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); + const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -5548,12 +5547,12 @@ namespace ts { return undefined; } - let scope: Node = undefined; + let scope: Node; - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations) { - for (let declaration of declarations) { - let container = getContainerNode(declaration); + for (const declaration of declarations) { + const container = getContainerNode(declaration); if (!container) { return undefined; @@ -5579,7 +5578,7 @@ namespace ts { } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] { - let positions: number[] = []; + const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search // Also, need to make this work for unicode escapes. @@ -5589,9 +5588,9 @@ namespace ts { return positions; } - let text = sourceFile.text; - let sourceLength = text.length; - let symbolNameLength = symbolName.length; + const text = sourceFile.text; + const sourceLength = text.length; + const symbolNameLength = symbolName.length; let position = text.indexOf(symbolName, start); while (position >= 0) { @@ -5602,7 +5601,7 @@ namespace ts { // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). - let endPosition = position + symbolNameLength; + const endPosition = position + symbolNameLength; if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { @@ -5616,14 +5615,14 @@ namespace ts { } function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { - let references: ReferenceEntry[] = []; - let sourceFile = container.getSourceFile(); - let labelName = targetLabel.text; - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + const references: ReferenceEntry[] = []; + const sourceFile = container.getSourceFile(); + const labelName = targetLabel.text; + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -5635,14 +5634,14 @@ namespace ts { } }); - let definition: DefinitionInfo = { + const definition: DefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) - } + }; return [{ definition, references }]; } @@ -5687,19 +5686,19 @@ namespace ts { result: ReferencedSymbol[], symbolToIndex: number[]): void { - let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* { cancellationToken.throwIfCancellationRequested(); - let referenceLocation = getTouchingPropertyName(sourceFile, position); + const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking @@ -5727,14 +5726,14 @@ namespace ts { return; } - let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); if (referenceSymbol) { - let referenceSymbolDeclaration = referenceSymbol.valueDeclaration; - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - let relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); if (relatedSymbol) { - let referencedSymbol = getReferencedSymbol(relatedSymbol); + const referencedSymbol = getReferencedSymbol(relatedSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation)); } /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment @@ -5744,7 +5743,7 @@ namespace ts { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) { - let referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } @@ -5754,7 +5753,7 @@ namespace ts { return; function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { - let symbolId = getSymbolId(symbol); + const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { index = result.length; @@ -5773,7 +5772,7 @@ namespace ts { return isInCommentHelper(sourceFile, position, isNonReferenceComment); function isNonReferenceComment(c: CommentRange): boolean { - let commentText = sourceFile.text.substring(c.pos, c.end); + const commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); } } @@ -5802,20 +5801,20 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; - let sourceFile = searchSpaceNode.getSourceFile(); - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + const sourceFile = searchSpaceNode.getSourceFile(); + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; } - let container = getSuperContainer(node, /*includeFunctions*/ false); + const container = getSuperContainer(node, /*includeFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space @@ -5825,7 +5824,7 @@ namespace ts { } }); - let definition = getDefinition(searchSpaceNode.symbol); + const definition = getDefinition(searchSpaceNode.symbol); return [{ definition, references }]; } @@ -5847,7 +5846,7 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - staticFlag &= searchSpaceNode.flags + staticFlag &= searchSpaceNode.flags; searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case SyntaxKind.SourceFile: @@ -5864,7 +5863,7 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -5874,7 +5873,7 @@ namespace ts { }); } else { - let sourceFile = searchSpaceNode.getSourceFile(); + const sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } @@ -5895,12 +5894,12 @@ namespace ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || (node.kind !== SyntaxKind.ThisKeyword && node.kind !== SyntaxKind.ThisType)) { return; } - let container = getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: @@ -5955,13 +5954,13 @@ namespace ts { * property name and variable declaration of the identifier. * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service * should show both 'name' in 'obj' and 'name' in variable declaration - * let name = "Foo"; - * let obj = { name }; + * const name = "Foo"; + * const obj = { name }; * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration * will be included correctly. */ - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); if (shorthandValueSymbol) { result.push(shorthandValueSymbol); } @@ -6008,9 +6007,9 @@ namespace ts { function getPropertySymbolFromTypeReference(typeReference: ExpressionWithTypeArguments) { if (typeReference) { - let type = typeChecker.getTypeAtLocation(typeReference); + const type = typeChecker.getTypeAtLocation(typeReference); if (type) { - let propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + const propertySymbol = typeChecker.getPropertyOfType(type, propertyName); if (propertySymbol) { result.push(propertySymbol); } @@ -6030,7 +6029,7 @@ namespace ts { // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { - let aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); + const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); if (searchSymbols.indexOf(aliasedSymbol) >= 0) { return aliasedSymbol; } @@ -6056,7 +6055,7 @@ namespace ts { // Finally, try all properties with the same name in any type the containing type extended or implemented, and // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - let result: Symbol[] = []; + const result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } @@ -6067,21 +6066,21 @@ namespace ts { function getPropertySymbolsFromContextualType(node: Node): Symbol[] { if (isNameOfPropertyAssignment(node)) { - let objectLiteral = node.parent.parent; - let contextualType = typeChecker.getContextualType(objectLiteral); - let name = (node).text; + const objectLiteral = node.parent.parent; + const contextualType = typeChecker.getContextualType(objectLiteral); + const name = (node).text; if (contextualType) { if (contextualType.flags & TypeFlags.Union) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - let unionProperty = contextualType.getProperty(name) + const unionProperty = contextualType.getProperty(name); if (unionProperty) { return [unionProperty]; } else { - let result: Symbol[] = []; + const result: Symbol[] = []; forEach((contextualType).types, t => { - let symbol = t.getProperty(name); + const symbol = t.getProperty(name); if (symbol) { result.push(symbol); } @@ -6090,7 +6089,7 @@ namespace ts { } } else { - let symbol = contextualType.getProperty(name); + const symbol = contextualType.getProperty(name); if (symbol) { return [symbol]; } @@ -6119,8 +6118,8 @@ namespace ts { // Remember the last meaning lastIterationMeaning = meaning; - for (let declaration of declarations) { - let declarationMeaning = getMeaningFromDeclaration(declaration); + for (const declaration of declarations) { + const declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -6155,13 +6154,13 @@ namespace ts { return true; } - let parent = node.parent; + const parent = node.parent; if (parent) { if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { return true; } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - let operator = (parent).operatorToken.kind; + const operator = (parent).operatorToken.kind; return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } @@ -6183,8 +6182,8 @@ namespace ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let outputFiles: OutputFile[] = []; + const sourceFile = getValidSourceFile(fileName); + const outputFiles: OutputFile[] = []; function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { outputFiles.push({ @@ -6194,7 +6193,7 @@ namespace ts { }); } - let emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken); return { outputFiles, @@ -6287,7 +6286,7 @@ namespace ts { } if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { - let decl = root.parent.parent.parent; + const decl = root.parent.parent.parent; return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent).token === SyntaxKind.ImplementsKeyword) || (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent).token === SyntaxKind.ExtendsKeyword); } @@ -6359,7 +6358,7 @@ namespace ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } @@ -6370,10 +6369,10 @@ namespace ts { } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - let node = getTouchingPropertyName(sourceFile, startPos); + const node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -6429,13 +6428,13 @@ namespace ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings()); } @@ -6467,11 +6466,11 @@ namespace ts { function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let result: number[] = []; - let classifiableNames = program.getClassifiableNames(); + const result: number[] = []; + const classifiableNames = program.getClassifiableNames(); processNode(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6483,7 +6482,7 @@ namespace ts { } function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return; } @@ -6531,19 +6530,19 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - let kind = node.kind; + const kind = node.kind; checkForClassificationCancellation(kind); if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { - let identifier = node; + const identifier = node; // Only bother calling into the typechecker if this is an identifier that // could possibly resolve to a type name. This makes classification run // in a third of the time it would normally take. if (classifiableNames[identifier.text]) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - let type = classifySymbol(symbol, getMeaningFromLocation(node)); + const type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { pushClassification(node.getStart(), node.getWidth(), type); } @@ -6583,8 +6582,8 @@ namespace ts { function convertClassifications(classifications: Classifications): ClassifiedSpan[] { Debug.assert(classifications.spans.length % 3 === 0); - let dense = classifications.spans; - let result: ClassifiedSpan[] = []; + const dense = classifications.spans; + const result: ClassifiedSpan[] = []; for (let i = 0, n = dense.length; i < n; i += 3) { result.push({ textSpan: createTextSpan(dense[i], dense[i + 1]), @@ -6601,15 +6600,15 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let spanStart = span.start; - let spanLength = span.length; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const spanStart = span.start; + const spanLength = span.length; // Make a scanner we can get trivia from. - let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); - let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); + const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - let result: number[] = []; + const result: number[] = []; processElement(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6623,15 +6622,15 @@ namespace ts { function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { - let start = triviaScanner.getTextPos(); + const start = triviaScanner.getTextPos(); // only bother scanning if we have something that could be trivia. if (!couldStartTrivia(sourceFile.text, start)) { return start; } - let kind = triviaScanner.scan(); - let end = triviaScanner.getTextPos(); - let width = end - start; + const kind = triviaScanner.scan(); + const end = triviaScanner.getTextPos(); + const width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { @@ -6655,8 +6654,8 @@ namespace ts { } if (kind === SyntaxKind.ConflictMarkerTrivia) { - let text = sourceFile.text; - let ch = text.charCodeAt(start); + const text = sourceFile.text; + const ch = text.charCodeAt(start); // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. @@ -6677,7 +6676,7 @@ namespace ts { if (kind === SyntaxKind.MultiLineCommentTrivia) { // See if this is a doc comment. If so, we'll classify certain portions of it // specially. - let docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); + const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { docCommentAndDiagnostics.jsDocComment.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); @@ -6696,7 +6695,7 @@ namespace ts { function classifyJSDocComment(docComment: JSDocComment) { let pos = docComment.pos; - for (let tag of docComment.tags) { + for (const tag of docComment.tags) { // As we walk through each tag, classify the portion of text from the end of // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { @@ -6754,7 +6753,7 @@ namespace ts { } function processJSDocTemplateTag(tag: JSDocTemplateTag) { - for (let child of tag.getChildren()) { + for (const child of tag.getChildren()) { processElement(child); } } @@ -6776,11 +6775,11 @@ namespace ts { } function classifyDisabledCodeToken() { - let start = mergeConflictScanner.getTextPos(); - let tokenKind = mergeConflictScanner.scan(); - let end = mergeConflictScanner.getTextPos(); + const start = mergeConflictScanner.getTextPos(); + const tokenKind = mergeConflictScanner.scan(); + const end = mergeConflictScanner.getTextPos(); - let type = classifyTokenType(tokenKind); + const type = classifyTokenType(tokenKind); if (type) { pushClassification(start, end - start, type); } @@ -6791,12 +6790,12 @@ namespace ts { return; } - let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - let tokenWidth = token.end - tokenStart; + const tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { - let type = classifyTokenType(token.kind, token); + const type = classifyTokenType(token.kind, token); if (type) { pushClassification(tokenStart, tokenWidth, type); } @@ -6923,9 +6922,9 @@ namespace ts { if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); - let children = element.getChildren(sourceFile); + const children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { - let child = children[i]; + const child = children[i]; if (isToken(child)) { classifyToken(child); } @@ -6940,28 +6939,28 @@ namespace ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let result: TextSpan[] = []; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const result: TextSpan[] = []; - let token = getTouchingToken(sourceFile, position); + const token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { - let matchKind = getMatchingTokenKind(token); + const matchKind = getMatchingTokenKind(token); // Ensure that there is a corresponding token to match ours. if (matchKind) { - let parentElement = token.parent; + const parentElement = token.parent; - let childNodes = parentElement.getChildren(sourceFile); - for (let current of childNodes) { + const childNodes = parentElement.getChildren(sourceFile); + for (const current of childNodes) { if (current.kind === matchKind) { - let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start < range2.start) { @@ -6981,11 +6980,11 @@ namespace ts { function getMatchingTokenKind(token: Node): ts.SyntaxKind { switch (token.kind) { - case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken + case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken; case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken; case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken; case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken + case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken; case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken; case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken; case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken; @@ -6997,29 +6996,29 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); - let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start)); return result; } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -7055,16 +7054,16 @@ namespace ts { * be performed. */ function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { - let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const start = new Date().getTime(); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return undefined; } - let tokenAtPos = getTokenAtPosition(sourceFile, position); - let tokenStart = tokenAtPos.getStart() + const tokenAtPos = getTokenAtPosition(sourceFile, position); + const tokenStart = tokenAtPos.getStart(); if (!tokenAtPos || tokenStart < position) { return undefined; } @@ -7100,11 +7099,11 @@ namespace ts { return undefined; } - let parameters = getParametersForJsDocOwningNode(commentOwner); - let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + const parameters = getParametersForJsDocOwningNode(commentOwner); + const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + const lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; @@ -7128,7 +7127,7 @@ namespace ts { // * if the caret was directly in front of the object, then we add an extra line and indentation. const preamble = "/**" + newLine + indentationStr + " * "; - let result = + const result = preamble + newLine + docParams + indentationStr + " */" + @@ -7172,7 +7171,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return (rightHandSide).parameters; case SyntaxKind.ClassExpression: - for (let member of (rightHandSide).members) { + for (const member of (rightHandSide).members) { if (member.kind === SyntaxKind.Constructor) { return (member).parameters; } @@ -7192,15 +7191,15 @@ namespace ts { // anything away. synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); - let fileContents = sourceFile.text; - let result: TodoComment[] = []; + const fileContents = sourceFile.text; + const result: TodoComment[] = []; if (descriptors.length > 0) { - let regExp = getTodoCommentsRegExp(); + const regExp = getTodoCommentsRegExp(); let matchArray: RegExpExecArray; while (matchArray = regExp.exec(fileContents)) { @@ -7223,15 +7222,15 @@ namespace ts { // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. - let firstDescriptorCaptureIndex = 3; + const firstDescriptorCaptureIndex = 3; Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); - let preamble = matchArray[1]; - let matchPosition = matchArray.index + preamble.length; + const preamble = matchArray[1]; + const matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - let token = getTokenAtPosition(sourceFile, matchPosition); + const token = getTokenAtPosition(sourceFile, matchPosition); if (!isInsideComment(sourceFile, token, matchPosition)) { continue; } @@ -7250,7 +7249,7 @@ namespace ts { continue; } - let message = matchArray[2]; + const message = matchArray[2]; result.push({ descriptor: descriptor, message: message, @@ -7281,14 +7280,14 @@ namespace ts { // // The following three regexps are used to match the start of the text up to the TODO // comment portion. - let singleLineCommentStart = /(?:\/\/+\s*)/.source; - let multiLineCommentStart = /(?:\/\*+\s*)/.source; - let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + const singleLineCommentStart = /(?:\/\/+\s*)/.source; + const multiLineCommentStart = /(?:\/\*+\s*)/.source; + const anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + const preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -7298,17 +7297,17 @@ namespace ts { // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). - let endOfLineOrEndOfComment = /(?:$|\*\/)/.source - let messageRemainder = /(?:.*?)/.source + const endOfLineOrEndOfComment = /(?:$|\*\/)/.source; + const messageRemainder = /(?:.*?)/.source; // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. - let messagePortion = "(" + literals + messageRemainder + ")"; - let regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + const messagePortion = "(" + literals + messageRemainder + ")"; + const regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim @@ -7334,40 +7333,40 @@ namespace ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol) { - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations && declarations.length > 0) { // Disallow rename for elements that are defined in the standard TypeScript library. - let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); + const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); if (defaultLibFileName) { - for (let current of declarations) { - let sourceFile = current.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + for (const current of declarations) { + const sourceFile = current.getSourceFile(); + const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) { return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); } } } - let displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - let kind = getSymbolKind(symbol, node); + const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const kind = getSymbolKind(symbol, node); if (kind) { return { canRename: true, - localizedErrorMessage: undefined, + kind, displayName, + localizedErrorMessage: undefined, fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kind: kind, kindModifiers: getSymbolModifiers(symbol), triggerSpan: createTextSpan(node.getStart(), node.getWidth()) }; @@ -7434,14 +7433,14 @@ namespace ts { /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { - initializeNameTable(sourceFile) + initializeNameTable(sourceFile); } return sourceFile.nameTable; } function initializeNameTable(sourceFile: SourceFile): void { - let nameTable: Map = {}; + const nameTable: Map = {}; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -7479,13 +7478,13 @@ namespace ts { /// Classifier export function createClassifier(): Classifier { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); /// We do not have a full parser support to know when we should parse a regex or not /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - let noRegexTable: boolean[] = []; + const noRegexTable: boolean[] = []; noRegexTable[SyntaxKind.Identifier] = true; noRegexTable[SyntaxKind.StringLiteral] = true; noRegexTable[SyntaxKind.NumericLiteral] = true; @@ -7519,7 +7518,7 @@ namespace ts { // // Where on the second line, you will get the 'return' keyword, // a string literal, and a template end consisting of '} } `'. - let templateStack: SyntaxKind[] = []; + const templateStack: SyntaxKind[] = []; /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { @@ -7545,18 +7544,18 @@ namespace ts { } function convertClassifications(classifications: Classifications, text: string): ClassificationResult { - let entries: ClassificationInfo[] = []; - let dense = classifications.spans; + const entries: ClassificationInfo[] = []; + const dense = classifications.spans; let lastEnd = 0; for (let i = 0, n = dense.length; i < n; i += 3) { - let start = dense[i]; - let length = dense[i + 1]; - let type = dense[i + 2]; + const start = dense[i]; + const length = dense[i + 1]; + const type = dense[i + 2]; // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { - let whitespaceLength = start - lastEnd; + const whitespaceLength = start - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7566,7 +7565,7 @@ namespace ts { lastEnd = start + length; } - let whitespaceLength = text.length - lastEnd; + const whitespaceLength = text.length - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7620,7 +7619,7 @@ namespace ts { // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { case EndOfLineState.InDoubleQuoteStringLiteral: - text = '"\\\n' + text; + text = "\"\\\n" + text; offset = 3; break; case EndOfLineState.InSingleQuoteStringLiteral: @@ -7646,7 +7645,7 @@ namespace ts { scanner.setText(text); - let result: Classifications = { + const result: Classifications = { endOfLineState: EndOfLineState.None, spans: [] }; @@ -7728,7 +7727,7 @@ namespace ts { // If we don't have anything on the template stack, // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { - let lastTemplateStackToken = lastOrUndefined(templateStack); + const lastTemplateStackToken = lastOrUndefined(templateStack); if (lastTemplateStackToken === SyntaxKind.TemplateHead) { token = scanner.reScanTemplateToken(); @@ -7758,17 +7757,17 @@ namespace ts { return result; function processToken(): void { - let start = scanner.getTokenPos(); - let end = scanner.getTextPos(); + const start = scanner.getTokenPos(); + const end = scanner.getTextPos(); addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) { // Check to see if we finished up on a multiline string literal. - let tokenText = scanner.getTokenText(); + const tokenText = scanner.getTokenText(); if (scanner.isUnterminated()) { - let lastCharIndex = tokenText.length - 1; + const lastCharIndex = tokenText.length - 1; let numBackslashes = 0; while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) { @@ -7777,7 +7776,7 @@ namespace ts { // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { - let quoteChar = tokenText.charCodeAt(0); + const quoteChar = tokenText.charCodeAt(0); result.endOfLineState = quoteChar === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; @@ -7826,7 +7825,7 @@ namespace ts { // relative to the original text. start -= offset; end -= offset; - let length = end - start; + const length = end - start; if (length > 0) { result.spans.push(start); @@ -7941,7 +7940,7 @@ namespace ts { } /// getDefaultLibraryFilePath - declare let __dirname: string; + declare const __dirname: string; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript From c0b0bebaa79d055bf23bde9e2a4c4eb5c7c97766 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 14 Dec 2015 14:04:14 -0800 Subject: [PATCH 53/75] Fix linting issue --- Jakefile.js | 3 +- src/services/services.ts | 1071 +++++++++++++++++++------------------- 2 files changed, 537 insertions(+), 537 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index beb16d2886f..91bd805a27b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -924,7 +924,8 @@ function lintFileAsync(options, path, cb) { var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) - .concat(scriptSources); + .concat(scriptSources) + .concat([path.join(servicesDirectory,"services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { diff --git a/src/services/services.ts b/src/services/services.ts index 8e2e4913edd..4109a4eb345 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -12,7 +12,7 @@ namespace ts { /** The version of the language service API */ - export let servicesVersion = "0.4" + export const servicesVersion = "0.4"; export interface Node { getSourceFile(): SourceFile; @@ -48,7 +48,7 @@ namespace ts { getConstructSignatures(): Signature[]; getStringIndexType(): Type; getNumberIndexType(): Type; - getBaseTypes(): ObjectType[] + getBaseTypes(): ObjectType[]; } export interface Signature { @@ -97,7 +97,7 @@ namespace ts { dispose?(): void; } - export module ScriptSnapshot { + export namespace ScriptSnapshot { class StringScriptSnapshot implements IScriptSnapshot { constructor(private text: string) { @@ -126,12 +126,12 @@ namespace ts { referencedFiles: FileReference[]; importedFiles: FileReference[]; ambientExternalModules: string[]; - isLibFile: boolean + isLibFile: boolean; } - let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - let emptyArray: any[] = []; + const emptyArray: any[] = []; const jsDocTagNames = [ "augments", @@ -174,7 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - let node = new NodeObject(kind, pos, end); + const node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; @@ -235,8 +235,8 @@ namespace ts { private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - let token = scanner.scan(); - let textPos = scanner.getTextPos(); + const token = scanner.scan(); + const textPos = scanner.getTextPos(); nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this)); pos = textPos; } @@ -244,13 +244,11 @@ namespace ts { } private createSyntaxList(nodes: NodeArray): Node { - let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); + const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); list._children = []; let pos = nodes.pos; - - - for (let node of nodes) { + for (const node of nodes) { if (pos < node.pos) { pos = this.addSyntheticNodes(list._children, pos, node.pos); } @@ -269,14 +267,14 @@ namespace ts { scanner.setText((sourceFile || this.getSourceFile()).text); children = []; let pos = this.pos; - let processNode = (node: Node) => { + const processNode = (node: Node) => { if (pos < node.pos) { pos = this.addSyntheticNodes(children, pos, node.pos); } children.push(node); pos = node.end; }; - let processNodes = (nodes: NodeArray) => { + const processNodes = (nodes: NodeArray) => { if (pos < nodes.pos) { pos = this.addSyntheticNodes(children, pos, nodes.pos); } @@ -308,20 +306,20 @@ namespace ts { } public getFirstToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - let child = children[0]; + const child = children[0]; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); - let child = lastOrUndefined(children); + const child = lastOrUndefined(children); if (!child) { return undefined; } @@ -366,8 +364,8 @@ namespace ts { } function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) { - let documentationComment = []; - let docComments = getJsDocCommentsSeparatedByNewLines(); + const documentationComment = []; + const docComments = getJsDocCommentsSeparatedByNewLines(); ts.forEach(docComments, docComment => { if (documentationComment.length) { documentationComment.push(lineBreakPart()); @@ -378,22 +376,22 @@ namespace ts { return documentationComment; function getJsDocCommentsSeparatedByNewLines() { - let paramTag = "@param"; - let jsDocCommentParts: SymbolDisplayPart[] = []; + const paramTag = "@param"; + const jsDocCommentParts: SymbolDisplayPart[] = []; ts.forEach(declarations, (declaration, indexOfDeclaration) => { // Make sure we are collecting doc comment from declaration once, // In case of union property there might be same declaration multiple times // which only varies in type parameter - // Eg. let a: Array | Array; a.length + // Eg. const a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array if (indexOf(declarations, declaration) === indexOfDeclaration) { - let sourceFileOfDeclaration = getSourceFileOfNode(declaration); + const sourceFileOfDeclaration = getSourceFileOfNode(declaration); // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) { ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedParamJsDocComment) { addRange(jsDocCommentParts, cleanedParamJsDocComment); } @@ -413,7 +411,7 @@ namespace ts { // Get the cleaned js doc comment text from the declaration ts.forEach(getJsDocCommentTextRange( declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedJsDocComment) { addRange(jsDocCommentParts, cleanedJsDocComment); } @@ -439,7 +437,7 @@ namespace ts { } for (; pos < end; pos++) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (!isWhiteSpace(ch) || isLineBreak(ch)) { // Either found lineBreak or non whiteSpace return pos; @@ -480,7 +478,7 @@ namespace ts { function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let spacesToRemoveAfterAsterisk: number; - let docComments: SymbolDisplayPart[] = []; + const docComments: SymbolDisplayPart[] = []; let blankLineCount = 0; let isInParamTag = false; @@ -491,7 +489,7 @@ namespace ts { // If the comment starts with '*' consume the spaces on this line if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - let lineStartPos = pos + 1; + const lineStartPos = pos + 1; pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); // Set the spaces to remove after asterisk as margin if not already set @@ -505,7 +503,7 @@ namespace ts { // Analyse text on this line while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - let ch = sourceFile.text.charAt(pos); + const ch = sourceFile.text.charAt(pos); if (ch === "@") { // If it is @param tag if (isParamTag(pos, end, sourceFile)) { @@ -544,7 +542,7 @@ namespace ts { function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let paramHelpStringMargin: number; - let paramDocComments: SymbolDisplayPart[] = []; + const paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { let blankLineCount = 0; @@ -559,7 +557,7 @@ namespace ts { if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; for (let curlies = 1; pos < end; pos++) { - let charCode = sourceFile.text.charCodeAt(pos); + const charCode = sourceFile.text.charCodeAt(pos); // { character means we need to find another } to match the found one if (charCode === CharacterCodes.openBrace) { @@ -603,9 +601,9 @@ namespace ts { } let paramHelpString = ""; - let firstLineParamHelpStringPos = pos; + const firstLineParamHelpStringPos = pos; while (pos < end) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { @@ -674,15 +672,15 @@ namespace ts { } // Now consume white spaces max - let startOfLinePos = pos; + const startOfLinePos = pos; pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); if (pos >= end) { return; } - let consumedSpaces = pos - startOfLinePos; + const consumedSpaces = pos - startOfLinePos; if (consumedSpaces < paramHelpStringMargin) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (ch === CharacterCodes.asterisk) { // Consume more spaces after asterisk pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); @@ -815,7 +813,7 @@ namespace ts { private namedDeclarations: Map; constructor(kind: SyntaxKind, pos: number, end: number) { - super(kind, pos, end) + super(kind, pos, end); } public update(newText: string, textChangeRange: TextChangeRange): SourceFile { @@ -843,16 +841,16 @@ namespace ts { } private computeNamedDeclarations(): Map { - let result: Map = {}; + const result: Map = {}; forEachChild(this, visit); return result; function addDeclaration(declaration: Declaration) { - let name = getDeclarationName(declaration); + const name = getDeclarationName(declaration); if (name) { - let declarations = getDeclarations(name); + const declarations = getDeclarations(name); declarations.push(declaration); } } @@ -863,13 +861,13 @@ namespace ts { function getDeclarationName(declaration: Declaration) { if (declaration.name) { - let result = getTextOfIdentifierOrLiteral(declaration.name); + const result = getTextOfIdentifierOrLiteral(declaration.name); if (result !== undefined) { return result; } if (declaration.name.kind === SyntaxKind.ComputedPropertyName) { - let expr = (declaration.name).expression; + const expr = (declaration.name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } @@ -899,12 +897,12 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - let functionDeclaration = node; - let declarationName = getDeclarationName(functionDeclaration); + const functionDeclaration = node; + const declarationName = getDeclarationName(functionDeclaration); if (declarationName) { - let declarations = getDeclarations(declarationName); - let lastDeclaration = lastOrUndefined(declarations); + const declarations = getDeclarations(declarationName); + const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { @@ -980,7 +978,7 @@ namespace ts { break; case SyntaxKind.ImportDeclaration: - let importClause = (node).importClause; + const importClause = (node).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -1113,8 +1111,8 @@ namespace ts { } export interface Classifications { - spans: number[], - endOfLineState: EndOfLineState + spans: number[]; + endOfLineState: EndOfLineState; } export interface ClassifiedSpan { @@ -1171,7 +1169,7 @@ namespace ts { highlightSpans: HighlightSpan[]; } - export module HighlightSpanKind { + export namespace HighlightSpanKind { export const none = "none"; export const definition = "definition"; export const reference = "reference"; @@ -1220,7 +1218,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } export interface DefinitionInfo { @@ -1500,7 +1498,7 @@ namespace ts { } // TODO: move these to enums - export module ScriptElementKind { + export namespace ScriptElementKind { export const unknown = ""; export const warning = "warning"; @@ -1529,7 +1527,7 @@ namespace ts { export const enumElement = "enum"; // Inside module and script only - // let v = .. + // const v = .. export const variableElement = "var"; // Inside function @@ -1581,7 +1579,7 @@ namespace ts { export const letElement = "let"; } - export module ScriptElementKindModifier { + export namespace ScriptElementKindModifier { export const none = ""; export const publicMemberModifier = "public"; export const privateMemberModifier = "private"; @@ -1723,8 +1721,8 @@ namespace ts { this.fileNameToEntry = createFileMap(); // Initialize the list with the root file names - let rootFileNames = host.getScriptFileNames(); - for (let fileName of rootFileNames) { + const rootFileNames = host.getScriptFileNames(); + for (const fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } @@ -1738,7 +1736,7 @@ namespace ts { private createEntry(fileName: string, path: Path) { let entry: HostFileInformation; - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, @@ -1760,7 +1758,7 @@ namespace ts { } public getOrCreateEntry(fileName: string): HostFileInformation { - let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName) + const path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName); if (this.contains(path)) { return this.getEntry(path); } @@ -1769,7 +1767,7 @@ namespace ts { } public getRootFileNames(): string[] { - let fileNames: string[] = []; + const fileNames: string[] = []; this.fileNameToEntry.forEachValue((path, value) => { if (value) { @@ -1781,12 +1779,12 @@ namespace ts { } public getVersion(path: Path): string { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.version; } public getScriptSnapshot(path: Path): IScriptSnapshot { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.scriptSnapshot; } } @@ -1803,22 +1801,22 @@ namespace ts { } public getCurrentSourceFile(fileName: string): SourceFile { - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - let version = this.host.getScriptVersion(fileName); + const version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } @@ -1863,7 +1861,7 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1879,21 +1877,22 @@ namespace ts { options.noResolve = true; // if jsx is specified then treat file as .tsx - let inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - let sourceFile = createSourceFile(inputFileName, input, options.target); + const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + const sourceFile = createSourceFile(inputFileName, input, options.target); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } sourceFile.renamedDependencies = transpileOptions.renamedDependencies; - let newLine = getNewLineCharacter(options); + const newLine = getNewLineCharacter(options); // Output let outputText: string; let sourceMapText: string; + // Create a compilerHost object to allow the compiler to read and write files - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined, writeFile: (name, text, writeByteOrderMark) => { if (fileExtensionIs(name, ".map")) { @@ -1914,7 +1913,7 @@ namespace ts { readFile: (fileName): string => "" }; - let program = createProgram([inputFileName], options, compilerHost); + const program = createProgram([inputFileName], options, compilerHost); let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { @@ -1934,15 +1933,15 @@ namespace ts { * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { - let output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); + const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); return output.outputText; } export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { - let text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - let sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); setSourceFileFields(sourceFile, scriptSnapshot, version); // after full parsing we can use table with interned strings as name table sourceFile.nameTable = sourceFile.identifiers; @@ -1961,12 +1960,12 @@ namespace ts { let newText: string; // grab the fragment from the beginning of the original text to the beginning of the span - let prefix = textChangeRange.span.start !== 0 + const prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text - let suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; @@ -1976,7 +1975,7 @@ namespace ts { } else { // it was actual edit, fetch the fragment of new text that correspond to new span - let changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1985,7 +1984,7 @@ namespace ts { : (changedText + suffix); } - let newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -2006,7 +2005,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { @@ -2019,15 +2018,15 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - let buckets: Map> = {}; - let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); + const buckets: Map> = {}; + const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyFromCompilationSettings(settings: CompilerOptions): string { return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + +"|" + settings.allowJs; } function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap { - let key = getKeyFromCompilationSettings(settings); + const key = getKeyFromCompilationSettings(settings); let bucket = lookUp(buckets, key); if (!bucket && createIfMissing) { buckets[key] = bucket = createFileMap(); @@ -2036,9 +2035,9 @@ namespace ts { } function reportStats() { - let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => { - let entries = lookUp(buckets, name); - let sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; + const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => { + const entries = lookUp(buckets, name); + const sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; entries.forEachValue((key, entry) => { sourceFiles.push({ name: key, @@ -2052,15 +2051,15 @@ namespace ts { sourceFiles }; }); - return JSON.stringify(bucketInfoArray, null, 2); + return JSON.stringify(bucketInfoArray, undefined, 2); } function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); } function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); } function acquireOrUpdateDocument( @@ -2070,14 +2069,14 @@ namespace ts { version: string, acquiring: boolean): SourceFile { - let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); let entry = bucket.get(path); if (!entry) { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); entry = { sourceFile: sourceFile, @@ -2109,12 +2108,12 @@ namespace ts { } function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void { - let bucket = getBucketForCompilationSettings(compilationSettings, false); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/false); Debug.assert(bucket !== undefined); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); - let entry = bucket.get(path); + const entry = bucket.get(path); entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); @@ -2132,19 +2131,19 @@ namespace ts { } export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { - let referencedFiles: FileReference[] = []; - let importedFiles: FileReference[] = []; + const referencedFiles: FileReference[] = []; + const importedFiles: FileReference[] = []; let ambientExternalModules: string[]; let isNoDefaultLib = false; function processTripleSlashDirectives(): void { - let commentRanges = getLeadingCommentRanges(sourceText, 0); + const commentRanges = getLeadingCommentRanges(sourceText, 0); forEach(commentRanges, commentRange => { - let comment = sourceText.substring(commentRange.pos, commentRange.end); - let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); + const comment = sourceText.substring(commentRange.pos, commentRange.end); + const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; - let fileReference = referencePathMatchResult.fileReference; + const fileReference = referencePathMatchResult.fileReference; if (fileReference) { referencedFiles.push(fileReference); } @@ -2160,8 +2159,8 @@ namespace ts { } function recordModuleName() { - let importPath = scanner.getTokenValue(); - let pos = scanner.getTokenPos(); + const importPath = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); importedFiles.push({ fileName: importPath, pos: pos, @@ -2213,7 +2212,7 @@ namespace ts { } } else if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2311,7 +2310,7 @@ namespace ts { if (token === SyntaxKind.Identifier || isKeyword(token)) { token = scanner.scan(); if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2410,7 +2409,7 @@ namespace ts { if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -2550,8 +2549,8 @@ namespace ts { return true; } else if (position === comment.end) { - let text = sourceFile.text; - let width = comment.end - comment.pos; + const text = sourceFile.text; + const width = comment.end - comment.pos; // is single line comment or just /* if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { return true; @@ -2583,7 +2582,7 @@ namespace ts { } // A cache of completion entries for keywords, these do not change between sessions - let keywordCompletions: CompletionEntry[] = []; + const keywordCompletions: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { keywordCompletions.push({ name: tokenToString(i), @@ -2673,15 +2672,15 @@ namespace ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { - let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); + const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); let ruleProvider: formatting.RulesProvider; let program: Program; let lastProjectVersion: string; - let useCaseSensitivefileNames = false; - let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + const useCaseSensitivefileNames = false; + const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - let currentDirectory = host.getCurrentDirectory(); + const currentDirectory = host.getCurrentDirectory(); // Check if the localized messages json is set, otherwise query the host for it if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); @@ -2693,10 +2692,10 @@ namespace ts { } } - let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); function getValidSourceFile(fileName: string): SourceFile { - let sourceFile = program.getSourceFile(fileName); + const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); } @@ -2716,7 +2715,7 @@ namespace ts { function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { - let hostProjectVersion = host.getProjectVersion(); + const hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion) { return; @@ -2740,17 +2739,17 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - let oldSettings = program && program.getCompilerOptions(); - let newSettings = hostCache.compilationSettings(); - let changesInCompilationSettingsAffectSyntax = oldSettings && + const oldSettings = program && program.getCompilerOptions(); + const newSettings = hostCache.compilationSettings(); + const changesInCompilationSettingsAffectSyntax = oldSettings && (oldSettings.target !== newSettings.target || oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || + oldSettings.jsx !== newSettings.jsx || oldSettings.allowJs !== newSettings.allowJs); // Now create a new compiler - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, getCancellationToken: () => cancellationToken, getCanonicalFileName, @@ -2766,22 +2765,22 @@ namespace ts { }, readFile: (fileName): string => { // stub missing host functionality - let entry = hostCache.getOrCreateEntry(fileName); + const entry = hostCache.getOrCreateEntry(fileName); return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); } }; if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile) + compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); } - let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); // Release any files we have acquired in the old program but are // not part of the new program. if (program) { - let oldSourceFiles = program.getSourceFiles(); - for (let oldSourceFile of oldSourceFiles) { + const oldSourceFiles = program.getSourceFiles(); + for (const oldSourceFile of oldSourceFiles) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings); } @@ -2804,7 +2803,7 @@ namespace ts { // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. - let hostFileInformation = hostCache.getOrCreateEntry(fileName); + const hostFileInformation = hostCache.getOrCreateEntry(fileName); if (!hostFileInformation) { return undefined; } @@ -2814,7 +2813,7 @@ namespace ts { // can not be reused. we have to dump all syntax trees and create new ones. if (!changesInCompilationSettingsAffectSyntax) { // Check if the old program had this file already - let oldSourceFile = program && program.getSourceFile(fileName); + const oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to @@ -2851,7 +2850,7 @@ namespace ts { if (!sourceFile) { return false; } - let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + const path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); return sourceFile.version === hostCache.getVersion(path); } @@ -2862,13 +2861,13 @@ namespace ts { } // If number of files in the program do not match, it is not up-to-date - let rootFileNames = hostCache.getRootFileNames(); + const rootFileNames = hostCache.getRootFileNames(); if (program.getSourceFiles().length !== rootFileNames.length) { return false; } // If any file is not up-to-date, then the whole program is not up-to-date - for (let fileName of rootFileNames) { + for (const fileName of rootFileNames) { if (!sourceFileUpToDate(program.getSourceFile(fileName))) { return false; } @@ -2910,18 +2909,18 @@ namespace ts { function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); - let targetSourceFile = getValidSourceFile(fileName); + const targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. - let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics; } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return concatenate(semanticDiagnostics, declarationDiagnostics); } @@ -2937,14 +2936,14 @@ namespace ts { * @return undefined if the name is of external module otherwise a name with striped of any quote */ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, location: Node): string { - let displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); + const displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); if (displayName) { - let firstCharCode = displayName.charCodeAt(0); + const firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there) + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) return undefined; } } @@ -2987,20 +2986,20 @@ namespace ts { } function getCompletionData(fileName: string, position: number) { - let typeChecker = program.getTypeChecker(); - let syntacticStart = new Date().getTime(); - let sourceFile = getValidSourceFile(fileName); - let isJavaScriptFile = isSourceFileJavaScript(sourceFile); + const typeChecker = program.getTypeChecker(); + const syntacticStart = new Date().getTime(); + const sourceFile = getValidSourceFile(fileName); + const isJavaScriptFile = isSourceFileJavaScript(sourceFile); let isJsDocTagName = false; let start = new Date().getTime(); - let currentToken = getTokenAtPosition(sourceFile, position); + const currentToken = getTokenAtPosition(sourceFile, position); log("getCompletionData: Get current token: " + (new Date().getTime() - start)); start = new Date().getTime(); // Completion not allowed inside comments, bail out if this is the case - let insideComment = isInsideComment(sourceFile, currentToken, position); + const insideComment = isInsideComment(sourceFile, currentToken, position); log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { @@ -3014,7 +3013,7 @@ namespace ts { // /** @type {number | string} */ // Completion should work in the brackets let insideJsDocTagExpression = false; - let tag = getJsDocTagAtPosition(sourceFile, position); + const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { isJsDocTagName = true; @@ -3024,7 +3023,7 @@ namespace ts { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocReturnTag: - let tagWithExpression = tag; + const tagWithExpression = tag; if (tagWithExpression.typeExpression) { insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; } @@ -3045,7 +3044,7 @@ namespace ts { } start = new Date().getTime(); - let previousToken = findPrecedingToken(position, sourceFile); + const previousToken = findPrecedingToken(position, sourceFile); log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -3055,7 +3054,7 @@ namespace ts { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { - let start = new Date().getTime(); + const start = new Date().getTime(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start)); } @@ -3076,7 +3075,7 @@ namespace ts { return undefined; } - let { parent, kind } = contextToken; + const { parent, kind } = contextToken; if (kind === SyntaxKind.DotToken) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { node = (contextToken.parent).expression; @@ -3103,7 +3102,7 @@ namespace ts { } } - let semanticStart = new Date().getTime(); + const semanticStart = new Date().getTime(); let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; let symbols: Symbol[] = []; @@ -3112,7 +3111,7 @@ namespace ts { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - let tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value))); } @@ -3123,7 +3122,7 @@ namespace ts { isNewIdentifierLocation = false; } else if (isStartingCloseTag) { - let tagName = (contextToken.parent.parent).openingElement.tagName; + const tagName = (contextToken.parent.parent).openingElement.tagName; symbols = [typeChecker.getSymbolAtLocation(tagName)]; isMemberCompletion = true; @@ -3157,7 +3156,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members - let exportedSymbols = typeChecker.getExportsOfModule(symbol); + const exportedSymbols = typeChecker.getExportsOfModule(symbol); forEach(exportedSymbols, symbol => { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); @@ -3166,14 +3165,14 @@ namespace ts { } } - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); addTypeProperties(type); } function addTypeProperties(type: Type) { if (type) { // Filter private properties - for (let symbol of type.getApparentProperties()) { + for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } @@ -3185,8 +3184,8 @@ namespace ts { // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - let unionType = type; - for (let elementType of unionType.types) { + const unionType = type; + for (const elementType of unionType.types) { addTypeProperties(elementType); } } @@ -3256,14 +3255,14 @@ namespace ts { // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - let adjustedPosition = previousToken !== contextToken ? + const adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; - let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context - let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); return true; @@ -3282,8 +3281,8 @@ namespace ts { } function isCompletionListBlocker(contextToken: Node): boolean { - let start = new Date().getTime(); - let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + const start = new Date().getTime(); + const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken); @@ -3310,27 +3309,27 @@ namespace ts { function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { - let containingNodeKind = previousToken.parent.kind; + const containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.CallExpression // func( a, | || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ || containingNodeKind === SyntaxKind.NewExpression // new C(a, | || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === SyntaxKind.BinaryExpression // let x = (a, | + || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list| case SyntaxKind.OpenParenToken: return containingNodeKind === SyntaxKind.CallExpression // func( | || containingNodeKind === SyntaxKind.Constructor // constructor( | || containingNodeKind === SyntaxKind.NewExpression // new C(a| - || containingNodeKind === SyntaxKind.ParenthesizedExpression // let x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ case SyntaxKind.OpenBracketToken: return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === SyntaxKind.ComputedPropertyName // [ | /* this can become an index signature */ + || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ case SyntaxKind.ModuleKeyword: // module | case SyntaxKind.NamespaceKeyword: // namespace | @@ -3343,7 +3342,7 @@ namespace ts { return containingNodeKind === SyntaxKind.ClassDeclaration; // class A{ | case SyntaxKind.EqualsToken: - return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a| + return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| case SyntaxKind.TemplateHead: @@ -3375,8 +3374,8 @@ namespace ts { || contextToken.kind === SyntaxKind.StringLiteralType || contextToken.kind === SyntaxKind.RegularExpressionLiteral || isTemplateLiteralKind(contextToken.kind)) { - let start = contextToken.getStart(); - let end = contextToken.getEnd(); + const start = contextToken.getStart(); + const end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. @@ -3420,7 +3419,7 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); if (isVariableLike(rootDeclaration)) { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -3431,7 +3430,7 @@ namespace ts { } } else { - Debug.fail("Root declaration is not variable-like.") + Debug.fail("Root declaration is not variable-like."); } } else { @@ -3442,7 +3441,7 @@ namespace ts { return false; } - let typeMembers = typeChecker.getPropertiesOfType(typeForObject); + const typeMembers = typeChecker.getPropertiesOfType(typeForObject); if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, existingMembers); @@ -3466,11 +3465,11 @@ namespace ts { * @returns true if 'symbols' was successfully populated; false otherwise. */ function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { - let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? SyntaxKind.ImportDeclaration : SyntaxKind.ExportDeclaration; - let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); - let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + const importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + const moduleSpecifier = importOrExportDeclaration.moduleSpecifier; if (!moduleSpecifier) { return false; @@ -3480,7 +3479,7 @@ namespace ts { isNewIdentifierLocation = false; let exports: Symbol[]; - let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); if (moduleSpecifierSymbol) { exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } @@ -3497,9 +3496,9 @@ namespace ts { function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { if (contextToken) { switch (contextToken.kind) { - case SyntaxKind.OpenBraceToken: // let x = { | - case SyntaxKind.CommaToken: // let x = { a: 0, | - let parent = contextToken.parent; + case SyntaxKind.OpenBraceToken: // const x = { | + case SyntaxKind.CommaToken: // const x = { a: 0, | + const parent = contextToken.parent; if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { return parent; } @@ -3532,8 +3531,8 @@ namespace ts { function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { - let parent = contextToken.parent; - switch(contextToken.kind) { + const parent = contextToken.parent; + switch (contextToken.kind) { case SyntaxKind.LessThanSlashToken: case SyntaxKind.SlashToken: case SyntaxKind.Identifier: @@ -3596,7 +3595,7 @@ namespace ts { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - let containingNodeKind = contextToken.parent.kind; + const containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -3626,13 +3625,13 @@ namespace ts { case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { | containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface a { | - containingNodeKind === SyntaxKind.TypeLiteral; // let x : { | + containingNodeKind === SyntaxKind.TypeLiteral; // const x : { | case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && contextToken.parent && contextToken.parent.parent && (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // let x : { a; | + contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -3699,7 +3698,7 @@ namespace ts { function isDotOfNumericLiteral(contextToken: Node): boolean { if (contextToken.kind === SyntaxKind.NumericLiteral) { - let text = contextToken.getFullText(); + const text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3716,15 +3715,15 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - let exisingImportsOrExports: Map = {}; + const exisingImportsOrExports: Map = {}; - for (let element of namedImportsOrExports) { + for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out if (element.getStart() <= position && position <= element.getEnd()) { continue; } - let name = element.propertyName || element.name; + const name = element.propertyName || element.name; exisingImportsOrExports[name.text] = true; } @@ -3746,8 +3745,8 @@ namespace ts { return contextualMemberSymbols; } - let existingMemberNames: Map = {}; - for (let m of existingMembers) { + const existingMemberNames: Map = {}; + for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment && @@ -3766,7 +3765,7 @@ namespace ts { if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).text + existingName = ((m).propertyName).text; } } else { @@ -3789,8 +3788,8 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - let seenNames: Map = {}; - for (let attr of attributes) { + const seenNames: Map = {}; + for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { continue; @@ -3809,21 +3808,21 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (!completionData) { return undefined; } - let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; + const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let entries: CompletionEntry[] = []; + const entries: CompletionEntry[] = []; if (isRightOfDot && isSourceFileJavaScript(sourceFile)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); @@ -3845,16 +3844,16 @@ namespace ts { return { isMemberCompletion, isNewIdentifierLocation, entries }; function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map): CompletionEntry[] { - let entries: CompletionEntry[] = []; - let target = program.getCompilerOptions().target; + const entries: CompletionEntry[] = []; + const target = program.getCompilerOptions().target; - let nameTable = getNameTable(sourceFile); - for (let name in nameTable) { + const nameTable = getNameTable(sourceFile); + for (const name in nameTable) { if (!uniqueNames[name]) { uniqueNames[name] = name; - let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true); + const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true); if (displayName) { - let entry = { + const entry = { name: displayName, kind: ScriptElementKind.warning, kindModifiers: "", @@ -3875,7 +3874,7 @@ namespace ts { kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - } + }; })); } @@ -3883,7 +3882,7 @@ namespace ts { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true, location); + const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location); if (!displayName) { return undefined; } @@ -3905,13 +3904,13 @@ namespace ts { } function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map { - let start = new Date().getTime(); - let uniqueNames: Map = {}; + const start = new Date().getTime(); + const uniqueNames: Map = {}; if (symbols) { - for (let symbol of symbols) { - let entry = createCompletionEntry(symbol, location); + for (const symbol of symbols) { + const entry = createCompletionEntry(symbol, location); if (entry) { - let id = escapeIdentifier(entry.name); + const id = escapeIdentifier(entry.name); if (!lookUp(uniqueNames, id)) { entries.push(entry); uniqueNames[id] = id; @@ -3929,19 +3928,19 @@ namespace ts { synchronizeHostData(); // Compute all the completion symbols again. - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (completionData) { - let { symbols, location } = completionData; + const { symbols, location } = completionData; // Find the symbol with the matching entry name. - let target = program.getCompilerOptions().target; + const target = program.getCompilerOptions().target; // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false, location) === entryName ? s : undefined); + const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined); if (symbol) { - let { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); + const { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); return { name: entryName, kindModifiers: getSymbolModifiers(symbol), @@ -3953,7 +3952,7 @@ namespace ts { } // Didn't find a symbol with this name. See if we can find a keyword instead. - let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); + const keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); if (keywordCompletion) { return { name: entryName, @@ -3969,7 +3968,7 @@ namespace ts { // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(symbol: Symbol, location: Node): string { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; @@ -3978,7 +3977,7 @@ namespace ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); + const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -3990,7 +3989,7 @@ namespace ts { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; @@ -4019,8 +4018,8 @@ namespace ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { - let rootSymbolFlags = rootSymbol.getFlags(); + const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + const rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { return ScriptElementKind.memberVariableElement; } @@ -4028,8 +4027,8 @@ namespace ts { }); if (!unionPropertyKind) { // If this was union of all methods, - //make sure it has call signatures before we can label it as method - let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + // make sure it has call signatures before we can label it as method + const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -4053,11 +4052,11 @@ namespace ts { function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning = getMeaningFromLocation(location)) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let displayParts: SymbolDisplayPart[] = []; + const displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[]; - let symbolFlags = symbol.flags; + const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; let type: Type; @@ -4073,7 +4072,7 @@ namespace ts { type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - let right = (location.parent).name; + const right = (location.parent).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -4090,15 +4089,15 @@ namespace ts { } if (callExpression) { - let candidateSignatures: Signature[] = []; + const candidateSignatures: Signature[] = []; signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); if (!signature && candidateSignatures.length) { // Use the first candidate: signature = candidateSignatures[0]; } - let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; - let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; + const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -4156,8 +4155,8 @@ namespace ts { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - let functionDeclaration = location.parent; - let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + const functionDeclaration = location.parent; + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4226,8 +4225,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - let declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); - let isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); addFullSymbolName(symbol); @@ -4279,9 +4278,9 @@ namespace ts { } if (symbolFlags & SymbolFlags.EnumMember) { addPrefixForAnyFunctionOrVar(symbol, "enum member"); - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { - let constantValue = typeChecker.getConstantValue(declaration); + const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4297,7 +4296,7 @@ namespace ts { addFullSymbolName(symbol); ts.forEach(symbol.declarations, declaration => { if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { - let importEqualsDeclaration = declaration; + const importEqualsDeclaration = declaration; if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4308,7 +4307,7 @@ namespace ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4332,7 +4331,7 @@ namespace ts { displayParts.push(spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4347,7 +4346,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - let allSignatures = type.getCallSignatures(); + const allSignatures = type.getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } @@ -4370,7 +4369,7 @@ namespace ts { } function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) { - let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); addRange(displayParts, fullSymbolDisplayParts); } @@ -4416,7 +4415,7 @@ namespace ts { } function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4426,8 +4425,8 @@ namespace ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -4436,8 +4435,8 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const typeChecker = program.getTypeChecker(); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { // Try getting just type at this position and show @@ -4449,7 +4448,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -4464,7 +4463,7 @@ namespace ts { return undefined; } - let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); + const displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), @@ -4486,13 +4485,13 @@ namespace ts { } function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { - let typeChecker = program.getTypeChecker(); - let result: DefinitionInfo[] = []; - let declarations = symbol.getDeclarations(); - let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - let symbolKind = getSymbolKind(symbol, node); - let containerSymbol = symbol.parent; - let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + const typeChecker = program.getTypeChecker(); + const result: DefinitionInfo[] = []; + const declarations = symbol.getDeclarations(); + const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol + const symbolKind = getSymbolKind(symbol, node); + const containerSymbol = symbol.parent; + const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -4510,7 +4509,7 @@ namespace ts { if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { // Find the first class-like declaration and try to get the construct signature. - for (let declaration of symbol.getDeclarations()) { + for (const declaration of symbol.getDeclarations()) { if (isClassLike(declaration)) { return tryAddSignature(declaration.members, /*selectConstructors*/ true, @@ -4535,7 +4534,7 @@ namespace ts { } function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - let declarations: Declaration[] = []; + const declarations: Declaration[] = []; let definition: Declaration; forEach(signatureDeclarations, d => { @@ -4563,24 +4562,24 @@ namespace ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } // Labels if (isJumpStatementTarget(node)) { - let labelName = (node).text; - let label = getTargetLabel((node.parent), (node).text); + const labelName = (node).text; + const label = getTargetLabel((node.parent), (node).text); return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments - let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); + const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); if (comment) { - let referenceFile = tryResolveScriptReference(program, sourceFile, comment); + const referenceFile = tryResolveScriptReference(program, sourceFile, comment); if (referenceFile) { return [{ fileName: referenceFile.fileName, @@ -4594,7 +4593,7 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, @@ -4608,7 +4607,7 @@ namespace ts { // import {A, B} from "mod"; // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { symbol = typeChecker.getAliasedSymbol(symbol); } @@ -4620,15 +4619,15 @@ namespace ts { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); if (!shorthandSymbol) { return []; } - let shorthandDeclarations = shorthandSymbol.getDeclarations(); - let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); - let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + const shorthandDeclarations = shorthandSymbol.getDeclarations(); + const shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); + const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); + const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -4640,27 +4639,27 @@ namespace ts { function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; } - let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); if (!type) { return undefined; } if (type.flags & TypeFlags.Union) { - let result: DefinitionInfo[] = []; + const result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); @@ -4680,7 +4679,7 @@ namespace ts { let results = getOccurrencesAtPositionCore(fileName, position); if (results) { - let sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); + const sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); // Get occurrences only supports reporting occurrences for the file queried. So // filter down to that list. @@ -4694,10 +4693,10 @@ namespace ts { synchronizeHostData(); filesToSearch = map(filesToSearch, normalizeSlashes); - let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); - let sourceFile = getValidSourceFile(fileName); + const sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -4705,8 +4704,8 @@ namespace ts { return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); function getHighlightSpanForNode(node: Node): HighlightSpan { - let start = node.getStart(); - let end = node.getEnd(); + const start = node.getStart(); + const end = node.getEnd(); return { fileName: sourceFile.fileName, @@ -4723,7 +4722,7 @@ namespace ts { isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - let referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); return convertReferencedSymbols(referencedSymbols); } @@ -4734,11 +4733,11 @@ namespace ts { return undefined; } - let fileNameToDocumentHighlights: Map = {}; - let result: DocumentHighlights[] = []; - for (let referencedSymbol of referencedSymbols) { - for (let referenceEntry of referencedSymbol.references) { - let fileName = referenceEntry.fileName; + const fileNameToDocumentHighlights: Map = {}; + const result: DocumentHighlights[] = []; + for (const referencedSymbol of referencedSymbols) { + for (const referenceEntry of referencedSymbol.references) { + const fileName = referenceEntry.fileName; let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName); if (!documentHighlights) { documentHighlights = { fileName, highlightSpans: [] }; @@ -4759,9 +4758,9 @@ namespace ts { } function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] { - let fileName = sourceFile.fileName; + const fileName = sourceFile.fileName; - let highlightSpans = getHighlightSpans(node); + const highlightSpans = getHighlightSpans(node); if (!highlightSpans || highlightSpans.length === 0) { return undefined; } @@ -4865,7 +4864,7 @@ namespace ts { * into function boundaries and try-blocks with catch-clauses. */ function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] { - let statementAccumulator: ThrowStatement[] = [] + const statementAccumulator: ThrowStatement[] = []; aggregate(node); return statementAccumulator; @@ -4874,7 +4873,7 @@ namespace ts { statementAccumulator.push(node); } else if (node.kind === SyntaxKind.TryStatement) { - let tryStatement = node; + const tryStatement = node; if (tryStatement.catchClause) { aggregate(tryStatement.catchClause); @@ -4905,7 +4904,7 @@ namespace ts { let child: Node = throwStatement; while (child.parent) { - let parent = child.parent; + const parent = child.parent; if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; @@ -4914,7 +4913,7 @@ namespace ts { // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. if (parent.kind === SyntaxKind.TryStatement) { - let tryStatement = parent; + const tryStatement = parent; if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; @@ -4928,7 +4927,7 @@ namespace ts { } function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] { - let statementAccumulator: BreakOrContinueStatement[] = [] + const statementAccumulator: BreakOrContinueStatement[] = []; aggregate(node); return statementAccumulator; @@ -4944,7 +4943,7 @@ namespace ts { } function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { - let actualOwner = getBreakOrContinueOwner(statement); + const actualOwner = getBreakOrContinueOwner(statement); return actualOwner && actualOwner === owner; } @@ -4979,7 +4978,7 @@ namespace ts { } function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] { - let container = declaration.parent; + const container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { @@ -5009,8 +5008,8 @@ namespace ts { return undefined; } - let keywords: Node[] = []; - let modifierFlag: NodeFlags = getFlagFromModifier(modifier); + const keywords: Node[] = []; + const modifierFlag: NodeFlags = getFlagFromModifier(modifier); let nodes: Node[]; switch (container.kind) { @@ -5035,7 +5034,7 @@ namespace ts { // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - let constructor = forEach((container).members, member => { + const constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -5048,7 +5047,7 @@ namespace ts { } break; default: - Debug.fail("Invalid container kind.") + Debug.fail("Invalid container kind."); } forEach(nodes, node => { @@ -5091,7 +5090,7 @@ namespace ts { } function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor); tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor); @@ -5099,7 +5098,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void { - let accessor = getDeclarationOfKind(accessorSymbol, accessorKind); + const accessor = getDeclarationOfKind(accessorSymbol, accessorKind); if (accessor) { forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword)); @@ -5108,9 +5107,9 @@ namespace ts { } function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] { - let declarations = constructorDeclaration.symbol.getDeclarations() + const declarations = constructorDeclaration.symbol.getDeclarations(); - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(declarations, declaration => { forEach(declaration.getChildren(), token => { @@ -5122,12 +5121,12 @@ namespace ts { } function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { - let loopTokens = loopNode.getChildren(); + const loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { @@ -5137,7 +5136,7 @@ namespace ts { } } - let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { @@ -5149,7 +5148,7 @@ namespace ts { } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { - let owner = getBreakOrContinueOwner(breakOrContinueStatement); + const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { @@ -5158,7 +5157,7 @@ namespace ts { case SyntaxKind.ForOfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner) + return getLoopBreakContinueOccurrences(owner); case SyntaxKind.SwitchStatement: return getSwitchCaseDefaultOccurrences(owner); @@ -5169,7 +5168,7 @@ namespace ts { } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -5177,7 +5176,7 @@ namespace ts { forEach(switchStatement.caseBlock.clauses, clause => { pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { @@ -5190,7 +5189,7 @@ namespace ts { } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); @@ -5199,7 +5198,7 @@ namespace ts { } if (tryStatement.finallyBlock) { - let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } @@ -5207,13 +5206,13 @@ namespace ts { } function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] { - let owner = getThrowStatementOwner(throwStatement); + const owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(aggregateOwnedThrowStatements(owner), throwStatement => { pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword); @@ -5231,14 +5230,14 @@ namespace ts { } function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] { - let func = getContainingFunction(returnStatement); + const func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } - let keywords: Node[] = [] + const keywords: Node[] = []; forEachReturnStatement(func.body, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -5252,7 +5251,7 @@ namespace ts { } function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (ifStatement.parent).elseStatement === ifStatement) { @@ -5261,7 +5260,7 @@ namespace ts { // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (ifStatement) { - let children = ifStatement.getChildren(); + const children = ifStatement.getChildren(); pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. @@ -5272,20 +5271,20 @@ namespace ts { } if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) { - break + break; } ifStatement = ifStatement.elseStatement; } - let result: HighlightSpan[] = []; + const result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { - let elseKeyword = keywords[i]; - let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + const elseKeyword = keywords[i]; + const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. let shouldCombindElseAndIf = true; @@ -5328,9 +5327,9 @@ namespace ts { return undefined; } - let result: ReferenceEntry[] = []; - for (let entry of documentHighlights) { - for (let highlightSpan of entry.highlightSpans) { + const result: ReferenceEntry[] = []; + for (const entry of documentHighlights) { + for (const highlightSpan of entry.highlightSpans) { result.push({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -5348,9 +5347,9 @@ namespace ts { return undefined; } - let referenceEntries: ReferenceEntry[] = []; + const referenceEntries: ReferenceEntry[] = []; - for (let referenceSymbol of referenceSymbols) { + for (const referenceSymbol of referenceSymbols) { addRange(referenceEntries, referenceSymbol.references); } @@ -5358,17 +5357,17 @@ namespace ts { } function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - let referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + const referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number): ReferencedSymbol[]{ - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + function findReferences(fileName: string, position: number): ReferencedSymbol[] { + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); @@ -5377,17 +5376,17 @@ namespace ts { function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } if (node.kind !== SyntaxKind.Identifier && // TODO (drosen): This should be enabled in a later release - currently breaks rename. - //node.kind !== SyntaxKind.ThisKeyword && - //node.kind !== SyntaxKind.SuperKeyword && + // node.kind !== SyntaxKind.ThisKeyword && + // node.kind !== SyntaxKind.SuperKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -5398,12 +5397,12 @@ namespace ts { } function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - let labelDefinition = getTargetLabel((node.parent), (node).text); + const labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; @@ -5422,7 +5421,7 @@ namespace ts { return getReferencesForSuperKeyword(node); } - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -5430,7 +5429,7 @@ namespace ts { return undefined; } - let declarations = symbol.declarations; + const declarations = symbol.declarations; // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!declarations || !declarations.length) { @@ -5440,29 +5439,29 @@ namespace ts { let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references - let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); + const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - let declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). - let scope = getSymbolScope(symbol); + const scope = getSymbolScope(symbol); // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - let symbolToIndex: number[] = []; + const symbolToIndex: number[] = []; if (scope) { result = []; getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - let internedName = getInternedName(symbol, node, declarations) - for (let sourceFile of sourceFiles) { + const internedName = getInternedName(symbol, node, declarations); + for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - let nameTable = getNameTable(sourceFile); + const nameTable = getNameTable(sourceFile); if (lookUp(nameTable, internedName)) { result = result || []; @@ -5474,9 +5473,9 @@ namespace ts { return result; function getDefinition(symbol: Symbol): DefinitionInfo { - let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - let name = map(info.displayParts, p => p.text).join(""); - let declarations = symbol.declarations; + const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); + const name = map(info.displayParts, p => p.text).join(""); + const declarations = symbol.declarations; if (!declarations || declarations.length === 0) { return undefined; } @@ -5506,7 +5505,7 @@ namespace ts { // Try to get the local symbol if we're dealing with an 'export default' // since that symbol has the "true" name. - let localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); + const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); symbol = localExportDefaultSymbol || symbol; return stripQuotes(symbol.name); @@ -5523,14 +5522,14 @@ namespace ts { function getSymbolScope(symbol: Symbol): Node { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. - let valueDeclaration = symbol.valueDeclaration; + const valueDeclaration = symbol.valueDeclaration; if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } // If this is private property or method, the scope is the containing class if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { - let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); + const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -5548,12 +5547,12 @@ namespace ts { return undefined; } - let scope: Node = undefined; + let scope: Node; - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations) { - for (let declaration of declarations) { - let container = getContainerNode(declaration); + for (const declaration of declarations) { + const container = getContainerNode(declaration); if (!container) { return undefined; @@ -5579,7 +5578,7 @@ namespace ts { } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] { - let positions: number[] = []; + const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search // Also, need to make this work for unicode escapes. @@ -5589,9 +5588,9 @@ namespace ts { return positions; } - let text = sourceFile.text; - let sourceLength = text.length; - let symbolNameLength = symbolName.length; + const text = sourceFile.text; + const sourceLength = text.length; + const symbolNameLength = symbolName.length; let position = text.indexOf(symbolName, start); while (position >= 0) { @@ -5602,7 +5601,7 @@ namespace ts { // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). - let endPosition = position + symbolNameLength; + const endPosition = position + symbolNameLength; if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { @@ -5616,14 +5615,14 @@ namespace ts { } function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { - let references: ReferenceEntry[] = []; - let sourceFile = container.getSourceFile(); - let labelName = targetLabel.text; - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + const references: ReferenceEntry[] = []; + const sourceFile = container.getSourceFile(); + const labelName = targetLabel.text; + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -5635,14 +5634,14 @@ namespace ts { } }); - let definition: DefinitionInfo = { + const definition: DefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) - } + }; return [{ definition, references }]; } @@ -5687,19 +5686,19 @@ namespace ts { result: ReferencedSymbol[], symbolToIndex: number[]): void { - let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* { cancellationToken.throwIfCancellationRequested(); - let referenceLocation = getTouchingPropertyName(sourceFile, position); + const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking @@ -5727,14 +5726,14 @@ namespace ts { return; } - let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); if (referenceSymbol) { - let referenceSymbolDeclaration = referenceSymbol.valueDeclaration; - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - let relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); if (relatedSymbol) { - let referencedSymbol = getReferencedSymbol(relatedSymbol); + const referencedSymbol = getReferencedSymbol(relatedSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation)); } /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment @@ -5744,7 +5743,7 @@ namespace ts { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) { - let referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } @@ -5754,7 +5753,7 @@ namespace ts { return; function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { - let symbolId = getSymbolId(symbol); + const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { index = result.length; @@ -5773,7 +5772,7 @@ namespace ts { return isInCommentHelper(sourceFile, position, isNonReferenceComment); function isNonReferenceComment(c: CommentRange): boolean { - let commentText = sourceFile.text.substring(c.pos, c.end); + const commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); } } @@ -5802,20 +5801,20 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; - let sourceFile = searchSpaceNode.getSourceFile(); - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + const sourceFile = searchSpaceNode.getSourceFile(); + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; } - let container = getSuperContainer(node, /*includeFunctions*/ false); + const container = getSuperContainer(node, /*includeFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space @@ -5825,7 +5824,7 @@ namespace ts { } }); - let definition = getDefinition(searchSpaceNode.symbol); + const definition = getDefinition(searchSpaceNode.symbol); return [{ definition, references }]; } @@ -5847,7 +5846,7 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - staticFlag &= searchSpaceNode.flags + staticFlag &= searchSpaceNode.flags; searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case SyntaxKind.SourceFile: @@ -5864,7 +5863,7 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -5874,7 +5873,7 @@ namespace ts { }); } else { - let sourceFile = searchSpaceNode.getSourceFile(); + const sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } @@ -5895,12 +5894,12 @@ namespace ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || (node.kind !== SyntaxKind.ThisKeyword && node.kind !== SyntaxKind.ThisType)) { return; } - let container = getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: @@ -5955,13 +5954,13 @@ namespace ts { * property name and variable declaration of the identifier. * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service * should show both 'name' in 'obj' and 'name' in variable declaration - * let name = "Foo"; - * let obj = { name }; + * const name = "Foo"; + * const obj = { name }; * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration * will be included correctly. */ - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); if (shorthandValueSymbol) { result.push(shorthandValueSymbol); } @@ -6008,9 +6007,9 @@ namespace ts { function getPropertySymbolFromTypeReference(typeReference: ExpressionWithTypeArguments) { if (typeReference) { - let type = typeChecker.getTypeAtLocation(typeReference); + const type = typeChecker.getTypeAtLocation(typeReference); if (type) { - let propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + const propertySymbol = typeChecker.getPropertyOfType(type, propertyName); if (propertySymbol) { result.push(propertySymbol); } @@ -6030,7 +6029,7 @@ namespace ts { // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { - let aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); + const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); if (searchSymbols.indexOf(aliasedSymbol) >= 0) { return aliasedSymbol; } @@ -6056,7 +6055,7 @@ namespace ts { // Finally, try all properties with the same name in any type the containing type extended or implemented, and // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - let result: Symbol[] = []; + const result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } @@ -6067,21 +6066,21 @@ namespace ts { function getPropertySymbolsFromContextualType(node: Node): Symbol[] { if (isNameOfPropertyAssignment(node)) { - let objectLiteral = node.parent.parent; - let contextualType = typeChecker.getContextualType(objectLiteral); - let name = (node).text; + const objectLiteral = node.parent.parent; + const contextualType = typeChecker.getContextualType(objectLiteral); + const name = (node).text; if (contextualType) { if (contextualType.flags & TypeFlags.Union) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - let unionProperty = contextualType.getProperty(name) + const unionProperty = contextualType.getProperty(name); if (unionProperty) { return [unionProperty]; } else { - let result: Symbol[] = []; + const result: Symbol[] = []; forEach((contextualType).types, t => { - let symbol = t.getProperty(name); + const symbol = t.getProperty(name); if (symbol) { result.push(symbol); } @@ -6090,7 +6089,7 @@ namespace ts { } } else { - let symbol = contextualType.getProperty(name); + const symbol = contextualType.getProperty(name); if (symbol) { return [symbol]; } @@ -6119,8 +6118,8 @@ namespace ts { // Remember the last meaning lastIterationMeaning = meaning; - for (let declaration of declarations) { - let declarationMeaning = getMeaningFromDeclaration(declaration); + for (const declaration of declarations) { + const declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -6155,13 +6154,13 @@ namespace ts { return true; } - let parent = node.parent; + const parent = node.parent; if (parent) { if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { return true; } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - let operator = (parent).operatorToken.kind; + const operator = (parent).operatorToken.kind; return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } @@ -6183,8 +6182,8 @@ namespace ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let outputFiles: OutputFile[] = []; + const sourceFile = getValidSourceFile(fileName); + const outputFiles: OutputFile[] = []; function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { outputFiles.push({ @@ -6194,7 +6193,7 @@ namespace ts { }); } - let emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken); return { outputFiles, @@ -6287,7 +6286,7 @@ namespace ts { } if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { - let decl = root.parent.parent.parent; + const decl = root.parent.parent.parent; return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent).token === SyntaxKind.ImplementsKeyword) || (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent).token === SyntaxKind.ExtendsKeyword); } @@ -6359,7 +6358,7 @@ namespace ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } @@ -6370,10 +6369,10 @@ namespace ts { } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - let node = getTouchingPropertyName(sourceFile, startPos); + const node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -6429,13 +6428,13 @@ namespace ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings()); } @@ -6467,11 +6466,11 @@ namespace ts { function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let result: number[] = []; - let classifiableNames = program.getClassifiableNames(); + const result: number[] = []; + const classifiableNames = program.getClassifiableNames(); processNode(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6483,7 +6482,7 @@ namespace ts { } function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return; } @@ -6531,19 +6530,19 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - let kind = node.kind; + const kind = node.kind; checkForClassificationCancellation(kind); if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { - let identifier = node; + const identifier = node; // Only bother calling into the typechecker if this is an identifier that // could possibly resolve to a type name. This makes classification run // in a third of the time it would normally take. if (classifiableNames[identifier.text]) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - let type = classifySymbol(symbol, getMeaningFromLocation(node)); + const type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { pushClassification(node.getStart(), node.getWidth(), type); } @@ -6583,8 +6582,8 @@ namespace ts { function convertClassifications(classifications: Classifications): ClassifiedSpan[] { Debug.assert(classifications.spans.length % 3 === 0); - let dense = classifications.spans; - let result: ClassifiedSpan[] = []; + const dense = classifications.spans; + const result: ClassifiedSpan[] = []; for (let i = 0, n = dense.length; i < n; i += 3) { result.push({ textSpan: createTextSpan(dense[i], dense[i + 1]), @@ -6601,15 +6600,15 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let spanStart = span.start; - let spanLength = span.length; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const spanStart = span.start; + const spanLength = span.length; // Make a scanner we can get trivia from. - let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); - let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); + const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - let result: number[] = []; + const result: number[] = []; processElement(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6623,15 +6622,15 @@ namespace ts { function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { - let start = triviaScanner.getTextPos(); + const start = triviaScanner.getTextPos(); // only bother scanning if we have something that could be trivia. if (!couldStartTrivia(sourceFile.text, start)) { return start; } - let kind = triviaScanner.scan(); - let end = triviaScanner.getTextPos(); - let width = end - start; + const kind = triviaScanner.scan(); + const end = triviaScanner.getTextPos(); + const width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { @@ -6655,8 +6654,8 @@ namespace ts { } if (kind === SyntaxKind.ConflictMarkerTrivia) { - let text = sourceFile.text; - let ch = text.charCodeAt(start); + const text = sourceFile.text; + const ch = text.charCodeAt(start); // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. @@ -6677,7 +6676,7 @@ namespace ts { if (kind === SyntaxKind.MultiLineCommentTrivia) { // See if this is a doc comment. If so, we'll classify certain portions of it // specially. - let docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); + const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { docCommentAndDiagnostics.jsDocComment.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); @@ -6696,7 +6695,7 @@ namespace ts { function classifyJSDocComment(docComment: JSDocComment) { let pos = docComment.pos; - for (let tag of docComment.tags) { + for (const tag of docComment.tags) { // As we walk through each tag, classify the portion of text from the end of // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { @@ -6754,7 +6753,7 @@ namespace ts { } function processJSDocTemplateTag(tag: JSDocTemplateTag) { - for (let child of tag.getChildren()) { + for (const child of tag.getChildren()) { processElement(child); } } @@ -6776,11 +6775,11 @@ namespace ts { } function classifyDisabledCodeToken() { - let start = mergeConflictScanner.getTextPos(); - let tokenKind = mergeConflictScanner.scan(); - let end = mergeConflictScanner.getTextPos(); + const start = mergeConflictScanner.getTextPos(); + const tokenKind = mergeConflictScanner.scan(); + const end = mergeConflictScanner.getTextPos(); - let type = classifyTokenType(tokenKind); + const type = classifyTokenType(tokenKind); if (type) { pushClassification(start, end - start, type); } @@ -6791,12 +6790,12 @@ namespace ts { return; } - let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - let tokenWidth = token.end - tokenStart; + const tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { - let type = classifyTokenType(token.kind, token); + const type = classifyTokenType(token.kind, token); if (type) { pushClassification(tokenStart, tokenWidth, type); } @@ -6923,9 +6922,9 @@ namespace ts { if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); - let children = element.getChildren(sourceFile); + const children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { - let child = children[i]; + const child = children[i]; if (isToken(child)) { classifyToken(child); } @@ -6940,28 +6939,28 @@ namespace ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let result: TextSpan[] = []; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const result: TextSpan[] = []; - let token = getTouchingToken(sourceFile, position); + const token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { - let matchKind = getMatchingTokenKind(token); + const matchKind = getMatchingTokenKind(token); // Ensure that there is a corresponding token to match ours. if (matchKind) { - let parentElement = token.parent; + const parentElement = token.parent; - let childNodes = parentElement.getChildren(sourceFile); - for (let current of childNodes) { + const childNodes = parentElement.getChildren(sourceFile); + for (const current of childNodes) { if (current.kind === matchKind) { - let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start < range2.start) { @@ -6981,11 +6980,11 @@ namespace ts { function getMatchingTokenKind(token: Node): ts.SyntaxKind { switch (token.kind) { - case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken + case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken; case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken; case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken; case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken + case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken; case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken; case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken; case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken; @@ -6997,29 +6996,29 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); - let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start)); return result; } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -7055,16 +7054,16 @@ namespace ts { * be performed. */ function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { - let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const start = new Date().getTime(); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return undefined; } - let tokenAtPos = getTokenAtPosition(sourceFile, position); - let tokenStart = tokenAtPos.getStart() + const tokenAtPos = getTokenAtPosition(sourceFile, position); + const tokenStart = tokenAtPos.getStart(); if (!tokenAtPos || tokenStart < position) { return undefined; } @@ -7100,11 +7099,11 @@ namespace ts { return undefined; } - let parameters = getParametersForJsDocOwningNode(commentOwner); - let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + const parameters = getParametersForJsDocOwningNode(commentOwner); + const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + const lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; @@ -7128,7 +7127,7 @@ namespace ts { // * if the caret was directly in front of the object, then we add an extra line and indentation. const preamble = "/**" + newLine + indentationStr + " * "; - let result = + const result = preamble + newLine + docParams + indentationStr + " */" + @@ -7172,7 +7171,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return (rightHandSide).parameters; case SyntaxKind.ClassExpression: - for (let member of (rightHandSide).members) { + for (const member of (rightHandSide).members) { if (member.kind === SyntaxKind.Constructor) { return (member).parameters; } @@ -7192,15 +7191,15 @@ namespace ts { // anything away. synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); - let fileContents = sourceFile.text; - let result: TodoComment[] = []; + const fileContents = sourceFile.text; + const result: TodoComment[] = []; if (descriptors.length > 0) { - let regExp = getTodoCommentsRegExp(); + const regExp = getTodoCommentsRegExp(); let matchArray: RegExpExecArray; while (matchArray = regExp.exec(fileContents)) { @@ -7223,15 +7222,15 @@ namespace ts { // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. - let firstDescriptorCaptureIndex = 3; + const firstDescriptorCaptureIndex = 3; Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); - let preamble = matchArray[1]; - let matchPosition = matchArray.index + preamble.length; + const preamble = matchArray[1]; + const matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - let token = getTokenAtPosition(sourceFile, matchPosition); + const token = getTokenAtPosition(sourceFile, matchPosition); if (!isInsideComment(sourceFile, token, matchPosition)) { continue; } @@ -7250,7 +7249,7 @@ namespace ts { continue; } - let message = matchArray[2]; + const message = matchArray[2]; result.push({ descriptor: descriptor, message: message, @@ -7281,14 +7280,14 @@ namespace ts { // // The following three regexps are used to match the start of the text up to the TODO // comment portion. - let singleLineCommentStart = /(?:\/\/+\s*)/.source; - let multiLineCommentStart = /(?:\/\*+\s*)/.source; - let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + const singleLineCommentStart = /(?:\/\/+\s*)/.source; + const multiLineCommentStart = /(?:\/\*+\s*)/.source; + const anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + const preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -7298,17 +7297,17 @@ namespace ts { // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). - let endOfLineOrEndOfComment = /(?:$|\*\/)/.source - let messageRemainder = /(?:.*?)/.source + const endOfLineOrEndOfComment = /(?:$|\*\/)/.source; + const messageRemainder = /(?:.*?)/.source; // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. - let messagePortion = "(" + literals + messageRemainder + ")"; - let regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + const messagePortion = "(" + literals + messageRemainder + ")"; + const regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim @@ -7334,40 +7333,40 @@ namespace ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol) { - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations && declarations.length > 0) { // Disallow rename for elements that are defined in the standard TypeScript library. - let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); + const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); if (defaultLibFileName) { - for (let current of declarations) { - let sourceFile = current.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + for (const current of declarations) { + const sourceFile = current.getSourceFile(); + const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) { return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); } } } - let displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - let kind = getSymbolKind(symbol, node); + const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const kind = getSymbolKind(symbol, node); if (kind) { return { canRename: true, - localizedErrorMessage: undefined, + kind, displayName, + localizedErrorMessage: undefined, fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kind: kind, kindModifiers: getSymbolModifiers(symbol), triggerSpan: createTextSpan(node.getStart(), node.getWidth()) }; @@ -7434,14 +7433,14 @@ namespace ts { /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { - initializeNameTable(sourceFile) + initializeNameTable(sourceFile); } return sourceFile.nameTable; } function initializeNameTable(sourceFile: SourceFile): void { - let nameTable: Map = {}; + const nameTable: Map = {}; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -7479,13 +7478,13 @@ namespace ts { /// Classifier export function createClassifier(): Classifier { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); /// We do not have a full parser support to know when we should parse a regex or not /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - let noRegexTable: boolean[] = []; + const noRegexTable: boolean[] = []; noRegexTable[SyntaxKind.Identifier] = true; noRegexTable[SyntaxKind.StringLiteral] = true; noRegexTable[SyntaxKind.NumericLiteral] = true; @@ -7519,7 +7518,7 @@ namespace ts { // // Where on the second line, you will get the 'return' keyword, // a string literal, and a template end consisting of '} } `'. - let templateStack: SyntaxKind[] = []; + const templateStack: SyntaxKind[] = []; /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { @@ -7545,18 +7544,18 @@ namespace ts { } function convertClassifications(classifications: Classifications, text: string): ClassificationResult { - let entries: ClassificationInfo[] = []; - let dense = classifications.spans; + const entries: ClassificationInfo[] = []; + const dense = classifications.spans; let lastEnd = 0; for (let i = 0, n = dense.length; i < n; i += 3) { - let start = dense[i]; - let length = dense[i + 1]; - let type = dense[i + 2]; + const start = dense[i]; + const length = dense[i + 1]; + const type = dense[i + 2]; // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { - let whitespaceLength = start - lastEnd; + const whitespaceLength = start - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7566,7 +7565,7 @@ namespace ts { lastEnd = start + length; } - let whitespaceLength = text.length - lastEnd; + const whitespaceLength = text.length - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7620,7 +7619,7 @@ namespace ts { // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { case EndOfLineState.InDoubleQuoteStringLiteral: - text = '"\\\n' + text; + text = "\"\\\n" + text; offset = 3; break; case EndOfLineState.InSingleQuoteStringLiteral: @@ -7646,7 +7645,7 @@ namespace ts { scanner.setText(text); - let result: Classifications = { + const result: Classifications = { endOfLineState: EndOfLineState.None, spans: [] }; @@ -7728,7 +7727,7 @@ namespace ts { // If we don't have anything on the template stack, // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { - let lastTemplateStackToken = lastOrUndefined(templateStack); + const lastTemplateStackToken = lastOrUndefined(templateStack); if (lastTemplateStackToken === SyntaxKind.TemplateHead) { token = scanner.reScanTemplateToken(); @@ -7758,17 +7757,17 @@ namespace ts { return result; function processToken(): void { - let start = scanner.getTokenPos(); - let end = scanner.getTextPos(); + const start = scanner.getTokenPos(); + const end = scanner.getTextPos(); addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) { // Check to see if we finished up on a multiline string literal. - let tokenText = scanner.getTokenText(); + const tokenText = scanner.getTokenText(); if (scanner.isUnterminated()) { - let lastCharIndex = tokenText.length - 1; + const lastCharIndex = tokenText.length - 1; let numBackslashes = 0; while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) { @@ -7777,7 +7776,7 @@ namespace ts { // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { - let quoteChar = tokenText.charCodeAt(0); + const quoteChar = tokenText.charCodeAt(0); result.endOfLineState = quoteChar === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; @@ -7826,7 +7825,7 @@ namespace ts { // relative to the original text. start -= offset; end -= offset; - let length = end - start; + const length = end - start; if (length > 0) { result.spans.push(start); @@ -7941,7 +7940,7 @@ namespace ts { } /// getDefaultLibraryFilePath - declare let __dirname: string; + declare const __dirname: string; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript From 5cbf17d989d6f746de480631fa6b05d43d1afd8f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Dec 2015 14:16:31 -0800 Subject: [PATCH 54/75] Added tests. --- .../stringLiteralTypesAsTags02.ts | 42 +++++++++++++++++ .../stringLiteralTypesAsTags03.ts | 46 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts create mode 100644 tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts new file mode 100644 index 00000000000..9fdc942a3f2 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts @@ -0,0 +1,42 @@ +// @declaration: true + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +function hasKind(entity: Entity, kind: "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file diff --git a/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts new file mode 100644 index 00000000000..96011d27255 --- /dev/null +++ b/tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts @@ -0,0 +1,46 @@ +// @declaration: true + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is Entity { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} \ No newline at end of file From 2efa69773d5e7fb208e2a03e52758189e058d266 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Dec 2015 14:24:55 -0800 Subject: [PATCH 55/75] Accepted baselines. --- .../stringLiteralTypesAsTags02.errors.txt | 50 ++++++++ .../reference/stringLiteralTypesAsTags02.js | 81 ++++++++++++ .../reference/stringLiteralTypesAsTags03.js | 85 +++++++++++++ .../stringLiteralTypesAsTags03.symbols | 109 ++++++++++++++++ .../stringLiteralTypesAsTags03.types | 118 ++++++++++++++++++ 5 files changed, 443 insertions(+) create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags02.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.js create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.symbols create mode 100644 tests/baselines/reference/stringLiteralTypesAsTags03.types diff --git a/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt b/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt new file mode 100644 index 00000000000..077113632d0 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags02.errors.txt @@ -0,0 +1,50 @@ +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts(18,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. +tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts(19,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + + +==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags02.ts (2 errors) ==== + + type Kind = "A" | "B" + + interface Entity { + kind: Kind; + } + + interface A extends Entity { + kind: "A"; + a: number; + } + + interface B extends Entity { + kind: "B"; + b: string; + } + + function hasKind(entity: Entity, kind: "A"): entity is A; + ~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + function hasKind(entity: Entity, kind: "B"): entity is B; + ~~~~~~~ +!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. + function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; + } + + let x: A = { + kind: "A", + a: 100, + } + + if (hasKind(x, "A")) { + let a = x; + } + else { + let b = x; + } + + if (!hasKind(x, "B")) { + let c = x; + } + else { + let d = x; + } \ No newline at end of file diff --git a/tests/baselines/reference/stringLiteralTypesAsTags02.js b/tests/baselines/reference/stringLiteralTypesAsTags02.js new file mode 100644 index 00000000000..e83f1ad46ee --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags02.js @@ -0,0 +1,81 @@ +//// [stringLiteralTypesAsTags02.ts] + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +function hasKind(entity: Entity, kind: "A"): entity is A; +function hasKind(entity: Entity, kind: "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is (A | B) { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} + +//// [stringLiteralTypesAsTags02.js] +function hasKind(entity, kind) { + return entity.kind === kind; +} +var x = { + kind: "A", + a: 100 +}; +if (hasKind(x, "A")) { + var a = x; +} +else { + var b = x; +} +if (!hasKind(x, "B")) { + var c = x; +} +else { + var d = x; +} + + +//// [stringLiteralTypesAsTags02.d.ts] +declare type Kind = "A" | "B"; +interface Entity { + kind: Kind; +} +interface A extends Entity { + kind: "A"; + a: number; +} +interface B extends Entity { + kind: "B"; + b: string; +} +declare function hasKind(entity: Entity, kind: "A"): entity is A; +declare function hasKind(entity: Entity, kind: "B"): entity is B; +declare let x: A; diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.js b/tests/baselines/reference/stringLiteralTypesAsTags03.js new file mode 100644 index 00000000000..bb2ed56040e --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.js @@ -0,0 +1,85 @@ +//// [stringLiteralTypesAsTags03.ts] + +type Kind = "A" | "B" + +interface Entity { + kind: Kind; +} + +interface A extends Entity { + kind: "A"; + a: number; +} + +interface B extends Entity { + kind: "B"; + b: string; +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +function hasKind(entity: Entity, kind: Kind): entity is Entity { + return entity.kind === kind; +} + +let x: A = { + kind: "A", + a: 100, +} + +if (hasKind(x, "A")) { + let a = x; +} +else { + let b = x; +} + +if (!hasKind(x, "B")) { + let c = x; +} +else { + let d = x; +} + +//// [stringLiteralTypesAsTags03.js] +function hasKind(entity, kind) { + return entity.kind === kind; +} +var x = { + kind: "A", + a: 100 +}; +if (hasKind(x, "A")) { + var a = x; +} +else { + var b = x; +} +if (!hasKind(x, "B")) { + var c = x; +} +else { + var d = x; +} + + +//// [stringLiteralTypesAsTags03.d.ts] +declare type Kind = "A" | "B"; +interface Entity { + kind: Kind; +} +interface A extends Entity { + kind: "A"; + a: number; +} +interface B extends Entity { + kind: "B"; + b: string; +} +declare function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +declare function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +declare let x: A; diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.symbols b/tests/baselines/reference/stringLiteralTypesAsTags03.symbols new file mode 100644 index 00000000000..3694daf8e00 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.symbols @@ -0,0 +1,109 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts === + +type Kind = "A" | "B" +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) + +interface Entity { +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: Kind; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) +} + +interface A extends Entity { +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: "A"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 7, 28)) + + a: number; +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 8, 14)) +} + +interface B extends Entity { +>B : Symbol(B, Decl(stringLiteralTypesAsTags03.ts, 10, 1)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + kind: "B"; +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 12, 28)) + + b: string; +>b : Symbol(b, Decl(stringLiteralTypesAsTags03.ts, 13, 14)) +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 21, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 21, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 21, 17)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) + +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 22, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 22, 32)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 22, 17)) +>B : Symbol(B, Decl(stringLiteralTypesAsTags03.ts, 10, 1)) + +function hasKind(entity: Entity, kind: Kind): entity is Entity { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 23, 32)) +>Kind : Symbol(Kind, Decl(stringLiteralTypesAsTags03.ts, 0, 0)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>Entity : Symbol(Entity, Decl(stringLiteralTypesAsTags03.ts, 1, 21)) + + return entity.kind === kind; +>entity.kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>entity : Symbol(entity, Decl(stringLiteralTypesAsTags03.ts, 23, 17)) +>kind : Symbol(Entity.kind, Decl(stringLiteralTypesAsTags03.ts, 3, 18)) +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 23, 32)) +} + +let x: A = { +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +>A : Symbol(A, Decl(stringLiteralTypesAsTags03.ts, 5, 1)) + + kind: "A", +>kind : Symbol(kind, Decl(stringLiteralTypesAsTags03.ts, 27, 12)) + + a: 100, +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 28, 14)) +} + +if (hasKind(x, "A")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) + + let a = x; +>a : Symbol(a, Decl(stringLiteralTypesAsTags03.ts, 33, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} +else { + let b = x; +>b : Symbol(b, Decl(stringLiteralTypesAsTags03.ts, 36, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} + +if (!hasKind(x, "B")) { +>hasKind : Symbol(hasKind, Decl(stringLiteralTypesAsTags03.ts, 15, 1), Decl(stringLiteralTypesAsTags03.ts, 21, 63), Decl(stringLiteralTypesAsTags03.ts, 22, 63)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) + + let c = x; +>c : Symbol(c, Decl(stringLiteralTypesAsTags03.ts, 40, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} +else { + let d = x; +>d : Symbol(d, Decl(stringLiteralTypesAsTags03.ts, 43, 7)) +>x : Symbol(x, Decl(stringLiteralTypesAsTags03.ts, 27, 3)) +} diff --git a/tests/baselines/reference/stringLiteralTypesAsTags03.types b/tests/baselines/reference/stringLiteralTypesAsTags03.types new file mode 100644 index 00000000000..a1d83a1c058 --- /dev/null +++ b/tests/baselines/reference/stringLiteralTypesAsTags03.types @@ -0,0 +1,118 @@ +=== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags03.ts === + +type Kind = "A" | "B" +>Kind : "A" | "B" + +interface Entity { +>Entity : Entity + + kind: Kind; +>kind : "A" | "B" +>Kind : "A" | "B" +} + +interface A extends Entity { +>A : A +>Entity : Entity + + kind: "A"; +>kind : "A" + + a: number; +>a : number +} + +interface B extends Entity { +>B : B +>Entity : Entity + + kind: "B"; +>kind : "B" + + b: string; +>b : string +} + +// Currently (2015-12-14), we write '"A" | "A"' and '"B" | "B"' to avoid +// interpreting respective overloads as "specialized" signatures. +// That way, we can avoid the need to look for a compatible overload +// signature and simply check compatibility with the implementation. +function hasKind(entity: Entity, kind: "A" | "A"): entity is A; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "A" +>entity : any +>A : A + +function hasKind(entity: Entity, kind: "B" | "B"): entity is B; +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "B" +>entity : any +>B : B + +function hasKind(entity: Entity, kind: Kind): entity is Entity { +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>entity : Entity +>Entity : Entity +>kind : "A" | "B" +>Kind : "A" | "B" +>entity : any +>Entity : Entity + + return entity.kind === kind; +>entity.kind === kind : boolean +>entity.kind : "A" | "B" +>entity : Entity +>kind : "A" | "B" +>kind : "A" | "B" +} + +let x: A = { +>x : A +>A : A +>{ kind: "A", a: 100,} : { kind: "A"; a: number; } + + kind: "A", +>kind : "A" +>"A" : "A" + + a: 100, +>a : number +>100 : number +} + +if (hasKind(x, "A")) { +>hasKind(x, "A") : entity is A +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>x : A +>"A" : "A" + + let a = x; +>a : A +>x : A +} +else { + let b = x; +>b : A +>x : A +} + +if (!hasKind(x, "B")) { +>!hasKind(x, "B") : boolean +>hasKind(x, "B") : entity is B +>hasKind : { (entity: Entity, kind: "A"): entity is A; (entity: Entity, kind: "B"): entity is B; } +>x : A +>"B" : "B" + + let c = x; +>c : A +>x : A +} +else { + let d = x; +>d : A +>x : A +} From c0ff7f77a250e41a744dc56f7133c5808af1875e Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 14 Dec 2015 14:35:27 -0800 Subject: [PATCH 56/75] Fix build error --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index 092f987eb5a..4109a4eb345 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1948,7 +1948,7 @@ namespace ts { return sourceFile; } - export const disableIncrementalParsing = false; + export let disableIncrementalParsing = false; export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile { // If we were given a text change range, and our version or open-ness changed, then From 023e375835886c77278328663c79bf010f8f836e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 14 Dec 2015 16:44:26 -0800 Subject: [PATCH 57/75] Properly handle multiply-declared optional properties in JSX attr. type Fixes #6029 --- src/compiler/checker.ts | 15 +++++-- src/compiler/diagnosticMessages.json | 2 +- .../tsxAttributeResolution11.errors.txt | 33 +++++++++++++++ .../reference/tsxAttributeResolution11.js | 41 +++++++++++++++++++ .../jsx/tsxAttributeResolution11.tsx | 29 +++++++++++++ 5 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/tsxAttributeResolution11.errors.txt create mode 100644 tests/baselines/reference/tsxAttributeResolution11.js create mode 100644 tests/cases/conformance/jsx/tsxAttributeResolution11.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 78a7ccffbdd..09760b6b1e5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3766,11 +3766,13 @@ namespace ts { function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { const types = containingType.types; let props: Symbol[]; + let isOptional = !!(containingType.flags & TypeFlags.Intersection); for (const current of types) { const type = getApparentType(current); if (type !== unknownType) { const prop = getPropertyOfType(type, name); if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) { + isOptional = isOptional && !!(prop.flags & SymbolFlags.Optional); if (!props) { props = [prop]; } @@ -3798,7 +3800,12 @@ namespace ts { } propTypes.push(getTypeOfSymbol(prop)); } - const result = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name); + const result = createSymbol( + SymbolFlags.Property | + SymbolFlags.Transient | + SymbolFlags.SyntheticProperty | + (isOptional ? SymbolFlags.Optional : SymbolFlags.None), + name); result.containingType = containingType; result.declarations = declarations; result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes); @@ -8232,9 +8239,9 @@ namespace ts { // Props is of type 'any' or unknown return links.resolvedJsxType = attributesType; } - else if (!(attributesType.flags & TypeFlags.ObjectType)) { - // Props is not an object type - error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType)); + else if (attributesType.flags & TypeFlags.Union) { + // Props cannot be a union type + error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType)); return links.resolvedJsxType = anyType; } else { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 54123808932..1a2575e9da6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1691,7 +1691,7 @@ "category": "Error", "code": 2528 }, - "JSX element attributes type '{0}' must be an object type.": { + "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 }, diff --git a/tests/baselines/reference/tsxAttributeResolution11.errors.txt b/tests/baselines/reference/tsxAttributeResolution11.errors.txt new file mode 100644 index 00000000000..b043897d50d --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution11.errors.txt @@ -0,0 +1,33 @@ +tests/cases/conformance/jsx/file.tsx(11,22): error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'. + + +==== tests/cases/conformance/jsx/react.d.ts (0 errors) ==== + + declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } + } + +==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== + class MyComponent { + render() { + } + + props: { + ref?: string; + } + } + + // Should be an OK + var x = ; + ~~~ +!!! error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'. + + \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributeResolution11.js b/tests/baselines/reference/tsxAttributeResolution11.js new file mode 100644 index 00000000000..03b843c209a --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution11.js @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/jsx/tsxAttributeResolution11.tsx] //// + +//// [react.d.ts] + +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } +} + +//// [file.tsx] +class MyComponent { + render() { + } + + props: { + ref?: string; + } +} + +// Should be an OK +var x = ; + + + +//// [file.jsx] +var MyComponent = (function () { + function MyComponent() { + } + MyComponent.prototype.render = function () { + }; + return MyComponent; +}()); +// Should be an OK +var x = ; diff --git a/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx b/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx new file mode 100644 index 00000000000..fdff3c36fc7 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxAttributeResolution11.tsx @@ -0,0 +1,29 @@ +//@jsx: preserve +//@module: amd + +//@filename: react.d.ts +declare module JSX { + interface Element { } + interface IntrinsicElements { + } + interface ElementAttributesProperty { + props; + } + interface IntrinsicAttributes { + ref?: string; + } +} + +//@filename: file.tsx +class MyComponent { + render() { + } + + props: { + ref?: string; + } +} + +// Should be an OK +var x = ; + From ec95f9955af6507bba7b572ce913e48fd9639c94 Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 15 Dec 2015 10:04:30 -0800 Subject: [PATCH 58/75] Fix linting issue --- Jakefile.js | 3 +- src/services/services.ts | 1073 +++++++++++++++++++------------------- 2 files changed, 538 insertions(+), 538 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index beb16d2886f..91bd805a27b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -924,7 +924,8 @@ function lintFileAsync(options, path, cb) { var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) - .concat(scriptSources); + .concat(scriptSources) + .concat([path.join(servicesDirectory,"services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { diff --git a/src/services/services.ts b/src/services/services.ts index a9dda549ead..8f9028486aa 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -12,7 +12,7 @@ namespace ts { /** The version of the language service API */ - export let servicesVersion = "0.4" + export const servicesVersion = "0.4"; export interface Node { getSourceFile(): SourceFile; @@ -48,7 +48,7 @@ namespace ts { getConstructSignatures(): Signature[]; getStringIndexType(): Type; getNumberIndexType(): Type; - getBaseTypes(): ObjectType[] + getBaseTypes(): ObjectType[]; } export interface Signature { @@ -97,7 +97,7 @@ namespace ts { dispose?(): void; } - export module ScriptSnapshot { + export namespace ScriptSnapshot { class StringScriptSnapshot implements IScriptSnapshot { constructor(private text: string) { @@ -126,12 +126,12 @@ namespace ts { referencedFiles: FileReference[]; importedFiles: FileReference[]; ambientExternalModules: string[]; - isLibFile: boolean + isLibFile: boolean; } - let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - let emptyArray: any[] = []; + const emptyArray: any[] = []; const jsDocTagNames = [ "augments", @@ -174,7 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - let node = new NodeObject(kind, pos, end); + const node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; @@ -235,8 +235,8 @@ namespace ts { private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - let token = scanner.scan(); - let textPos = scanner.getTextPos(); + const token = scanner.scan(); + const textPos = scanner.getTextPos(); nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this)); pos = textPos; } @@ -244,13 +244,11 @@ namespace ts { } private createSyntaxList(nodes: NodeArray): Node { - let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); + const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); list._children = []; let pos = nodes.pos; - - - for (let node of nodes) { + for (const node of nodes) { if (pos < node.pos) { pos = this.addSyntheticNodes(list._children, pos, node.pos); } @@ -269,14 +267,14 @@ namespace ts { scanner.setText((sourceFile || this.getSourceFile()).text); children = []; let pos = this.pos; - let processNode = (node: Node) => { + const processNode = (node: Node) => { if (pos < node.pos) { pos = this.addSyntheticNodes(children, pos, node.pos); } children.push(node); pos = node.end; }; - let processNodes = (nodes: NodeArray) => { + const processNodes = (nodes: NodeArray) => { if (pos < nodes.pos) { pos = this.addSyntheticNodes(children, pos, nodes.pos); } @@ -308,20 +306,20 @@ namespace ts { } public getFirstToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - let child = children[0]; + const child = children[0]; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFile): Node { - let children = this.getChildren(sourceFile); + const children = this.getChildren(sourceFile); - let child = lastOrUndefined(children); + const child = lastOrUndefined(children); if (!child) { return undefined; } @@ -366,8 +364,8 @@ namespace ts { } function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) { - let documentationComment = []; - let docComments = getJsDocCommentsSeparatedByNewLines(); + const documentationComment = []; + const docComments = getJsDocCommentsSeparatedByNewLines(); ts.forEach(docComments, docComment => { if (documentationComment.length) { documentationComment.push(lineBreakPart()); @@ -378,22 +376,22 @@ namespace ts { return documentationComment; function getJsDocCommentsSeparatedByNewLines() { - let paramTag = "@param"; - let jsDocCommentParts: SymbolDisplayPart[] = []; + const paramTag = "@param"; + const jsDocCommentParts: SymbolDisplayPart[] = []; ts.forEach(declarations, (declaration, indexOfDeclaration) => { // Make sure we are collecting doc comment from declaration once, // In case of union property there might be same declaration multiple times // which only varies in type parameter - // Eg. let a: Array | Array; a.length + // Eg. const a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array if (indexOf(declarations, declaration) === indexOfDeclaration) { - let sourceFileOfDeclaration = getSourceFileOfNode(declaration); + const sourceFileOfDeclaration = getSourceFileOfNode(declaration); // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) { ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedParamJsDocComment) { addRange(jsDocCommentParts, cleanedParamJsDocComment); } @@ -413,7 +411,7 @@ namespace ts { // Get the cleaned js doc comment text from the declaration ts.forEach(getJsDocCommentTextRange( declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedJsDocComment) { addRange(jsDocCommentParts, cleanedJsDocComment); } @@ -439,7 +437,7 @@ namespace ts { } for (; pos < end; pos++) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (!isWhiteSpace(ch) || isLineBreak(ch)) { // Either found lineBreak or non whiteSpace return pos; @@ -480,7 +478,7 @@ namespace ts { function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let spacesToRemoveAfterAsterisk: number; - let docComments: SymbolDisplayPart[] = []; + const docComments: SymbolDisplayPart[] = []; let blankLineCount = 0; let isInParamTag = false; @@ -491,7 +489,7 @@ namespace ts { // If the comment starts with '*' consume the spaces on this line if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - let lineStartPos = pos + 1; + const lineStartPos = pos + 1; pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); // Set the spaces to remove after asterisk as margin if not already set @@ -505,7 +503,7 @@ namespace ts { // Analyse text on this line while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - let ch = sourceFile.text.charAt(pos); + const ch = sourceFile.text.charAt(pos); if (ch === "@") { // If it is @param tag if (isParamTag(pos, end, sourceFile)) { @@ -544,7 +542,7 @@ namespace ts { function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let paramHelpStringMargin: number; - let paramDocComments: SymbolDisplayPart[] = []; + const paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { let blankLineCount = 0; @@ -559,7 +557,7 @@ namespace ts { if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; for (let curlies = 1; pos < end; pos++) { - let charCode = sourceFile.text.charCodeAt(pos); + const charCode = sourceFile.text.charCodeAt(pos); // { character means we need to find another } to match the found one if (charCode === CharacterCodes.openBrace) { @@ -603,9 +601,9 @@ namespace ts { } let paramHelpString = ""; - let firstLineParamHelpStringPos = pos; + const firstLineParamHelpStringPos = pos; while (pos < end) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { @@ -674,15 +672,15 @@ namespace ts { } // Now consume white spaces max - let startOfLinePos = pos; + const startOfLinePos = pos; pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); if (pos >= end) { return; } - let consumedSpaces = pos - startOfLinePos; + const consumedSpaces = pos - startOfLinePos; if (consumedSpaces < paramHelpStringMargin) { - let ch = sourceFile.text.charCodeAt(pos); + const ch = sourceFile.text.charCodeAt(pos); if (ch === CharacterCodes.asterisk) { // Consume more spaces after asterisk pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); @@ -815,7 +813,7 @@ namespace ts { private namedDeclarations: Map; constructor(kind: SyntaxKind, pos: number, end: number) { - super(kind, pos, end) + super(kind, pos, end); } public update(newText: string, textChangeRange: TextChangeRange): SourceFile { @@ -843,16 +841,16 @@ namespace ts { } private computeNamedDeclarations(): Map { - let result: Map = {}; + const result: Map = {}; forEachChild(this, visit); return result; function addDeclaration(declaration: Declaration) { - let name = getDeclarationName(declaration); + const name = getDeclarationName(declaration); if (name) { - let declarations = getDeclarations(name); + const declarations = getDeclarations(name); declarations.push(declaration); } } @@ -863,13 +861,13 @@ namespace ts { function getDeclarationName(declaration: Declaration) { if (declaration.name) { - let result = getTextOfIdentifierOrLiteral(declaration.name); + const result = getTextOfIdentifierOrLiteral(declaration.name); if (result !== undefined) { return result; } if (declaration.name.kind === SyntaxKind.ComputedPropertyName) { - let expr = (declaration.name).expression; + const expr = (declaration.name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } @@ -899,12 +897,12 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - let functionDeclaration = node; - let declarationName = getDeclarationName(functionDeclaration); + const functionDeclaration = node; + const declarationName = getDeclarationName(functionDeclaration); if (declarationName) { - let declarations = getDeclarations(declarationName); - let lastDeclaration = lastOrUndefined(declarations); + const declarations = getDeclarations(declarationName); + const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { @@ -980,7 +978,7 @@ namespace ts { break; case SyntaxKind.ImportDeclaration: - let importClause = (node).importClause; + const importClause = (node).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -1113,8 +1111,8 @@ namespace ts { } export interface Classifications { - spans: number[], - endOfLineState: EndOfLineState + spans: number[]; + endOfLineState: EndOfLineState; } export interface ClassifiedSpan { @@ -1171,7 +1169,7 @@ namespace ts { highlightSpans: HighlightSpan[]; } - export module HighlightSpanKind { + export namespace HighlightSpanKind { export const none = "none"; export const definition = "definition"; export const reference = "reference"; @@ -1220,7 +1218,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number| string; + [s: string]: boolean | number | string; } export interface DefinitionInfo { @@ -1500,7 +1498,7 @@ namespace ts { } // TODO: move these to enums - export module ScriptElementKind { + export namespace ScriptElementKind { export const unknown = ""; export const warning = "warning"; @@ -1529,7 +1527,7 @@ namespace ts { export const enumElement = "enum"; // Inside module and script only - // let v = .. + // const v = .. export const variableElement = "var"; // Inside function @@ -1581,7 +1579,7 @@ namespace ts { export const letElement = "let"; } - export module ScriptElementKindModifier { + export namespace ScriptElementKindModifier { export const none = ""; export const publicMemberModifier = "public"; export const privateMemberModifier = "private"; @@ -1723,8 +1721,8 @@ namespace ts { this.fileNameToEntry = createFileMap(); // Initialize the list with the root file names - let rootFileNames = host.getScriptFileNames(); - for (let fileName of rootFileNames) { + const rootFileNames = host.getScriptFileNames(); + for (const fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } @@ -1738,7 +1736,7 @@ namespace ts { private createEntry(fileName: string, path: Path) { let entry: HostFileInformation; - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, @@ -1760,7 +1758,7 @@ namespace ts { } public getOrCreateEntry(fileName: string): HostFileInformation { - let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName) + const path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName); if (this.contains(path)) { return this.getEntry(path); } @@ -1769,7 +1767,7 @@ namespace ts { } public getRootFileNames(): string[] { - let fileNames: string[] = []; + const fileNames: string[] = []; this.fileNameToEntry.forEachValue((path, value) => { if (value) { @@ -1781,12 +1779,12 @@ namespace ts { } public getVersion(path: Path): string { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.version; } public getScriptSnapshot(path: Path): IScriptSnapshot { - let file = this.getEntry(path); + const file = this.getEntry(path); return file && file.scriptSnapshot; } } @@ -1803,22 +1801,22 @@ namespace ts { } public getCurrentSourceFile(fileName: string): SourceFile { - let scriptSnapshot = this.host.getScriptSnapshot(fileName); + const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - let version = this.host.getScriptVersion(fileName); + const version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } @@ -1863,7 +1861,7 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1879,21 +1877,22 @@ namespace ts { options.noResolve = true; // if jsx is specified then treat file as .tsx - let inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - let sourceFile = createSourceFile(inputFileName, input, options.target); + const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + const sourceFile = createSourceFile(inputFileName, input, options.target); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } sourceFile.renamedDependencies = transpileOptions.renamedDependencies; - let newLine = getNewLineCharacter(options); + const newLine = getNewLineCharacter(options); // Output let outputText: string; let sourceMapText: string; + // Create a compilerHost object to allow the compiler to read and write files - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined, writeFile: (name, text, writeByteOrderMark) => { if (fileExtensionIs(name, ".map")) { @@ -1914,7 +1913,7 @@ namespace ts { readFile: (fileName): string => "" }; - let program = createProgram([inputFileName], options, compilerHost); + const program = createProgram([inputFileName], options, compilerHost); let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { @@ -1934,15 +1933,15 @@ namespace ts { * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { - let output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); + const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); return output.outputText; } export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { - let text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - let sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); setSourceFileFields(sourceFile, scriptSnapshot, version); // after full parsing we can use table with interned strings as name table sourceFile.nameTable = sourceFile.identifiers; @@ -1961,12 +1960,12 @@ namespace ts { let newText: string; // grab the fragment from the beginning of the original text to the beginning of the span - let prefix = textChangeRange.span.start !== 0 + const prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text - let suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; @@ -1976,7 +1975,7 @@ namespace ts { } else { // it was actual edit, fetch the fragment of new text that correspond to new span - let changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1985,7 +1984,7 @@ namespace ts { : (changedText + suffix); } - let newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -2006,7 +2005,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { @@ -2019,15 +2018,15 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - let buckets: Map> = {}; - let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); + const buckets: Map> = {}; + const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyFromCompilationSettings(settings: CompilerOptions): string { return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + +"|" + settings.allowJs; } function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap { - let key = getKeyFromCompilationSettings(settings); + const key = getKeyFromCompilationSettings(settings); let bucket = lookUp(buckets, key); if (!bucket && createIfMissing) { buckets[key] = bucket = createFileMap(); @@ -2036,9 +2035,9 @@ namespace ts { } function reportStats() { - let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => { - let entries = lookUp(buckets, name); - let sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; + const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => { + const entries = lookUp(buckets, name); + const sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; entries.forEachValue((key, entry) => { sourceFiles.push({ name: key, @@ -2052,15 +2051,15 @@ namespace ts { sourceFiles }; }); - return JSON.stringify(bucketInfoArray, null, 2); + return JSON.stringify(bucketInfoArray, undefined, 2); } function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); } function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); } function acquireOrUpdateDocument( @@ -2070,14 +2069,14 @@ namespace ts { version: string, acquiring: boolean): SourceFile { - let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); let entry = bucket.get(path); if (!entry) { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); entry = { sourceFile: sourceFile, @@ -2109,12 +2108,12 @@ namespace ts { } function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void { - let bucket = getBucketForCompilationSettings(compilationSettings, false); + const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/false); Debug.assert(bucket !== undefined); - let path = toPath(fileName, currentDirectory, getCanonicalFileName); + const path = toPath(fileName, currentDirectory, getCanonicalFileName); - let entry = bucket.get(path); + const entry = bucket.get(path); entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); @@ -2132,19 +2131,19 @@ namespace ts { } export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { - let referencedFiles: FileReference[] = []; - let importedFiles: FileReference[] = []; + const referencedFiles: FileReference[] = []; + const importedFiles: FileReference[] = []; let ambientExternalModules: string[]; let isNoDefaultLib = false; function processTripleSlashDirectives(): void { - let commentRanges = getLeadingCommentRanges(sourceText, 0); + const commentRanges = getLeadingCommentRanges(sourceText, 0); forEach(commentRanges, commentRange => { - let comment = sourceText.substring(commentRange.pos, commentRange.end); - let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); + const comment = sourceText.substring(commentRange.pos, commentRange.end); + const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; - let fileReference = referencePathMatchResult.fileReference; + const fileReference = referencePathMatchResult.fileReference; if (fileReference) { referencedFiles.push(fileReference); } @@ -2160,8 +2159,8 @@ namespace ts { } function recordModuleName() { - let importPath = scanner.getTokenValue(); - let pos = scanner.getTokenPos(); + const importPath = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); importedFiles.push({ fileName: importPath, pos: pos, @@ -2213,7 +2212,7 @@ namespace ts { } } else if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2311,7 +2310,7 @@ namespace ts { if (token === SyntaxKind.Identifier || isKeyword(token)) { token = scanner.scan(); if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { + if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } @@ -2410,7 +2409,7 @@ namespace ts { if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { continue; } else { @@ -2550,8 +2549,8 @@ namespace ts { return true; } else if (position === comment.end) { - let text = sourceFile.text; - let width = comment.end - comment.pos; + const text = sourceFile.text; + const width = comment.end - comment.pos; // is single line comment or just /* if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { return true; @@ -2583,7 +2582,7 @@ namespace ts { } // A cache of completion entries for keywords, these do not change between sessions - let keywordCompletions: CompletionEntry[] = []; + const keywordCompletions: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { keywordCompletions.push({ name: tokenToString(i), @@ -2673,15 +2672,15 @@ namespace ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { - let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); + const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); let ruleProvider: formatting.RulesProvider; let program: Program; let lastProjectVersion: string; - let useCaseSensitivefileNames = false; - let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + const useCaseSensitivefileNames = false; + const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - let currentDirectory = host.getCurrentDirectory(); + const currentDirectory = host.getCurrentDirectory(); // Check if the localized messages json is set, otherwise query the host for it if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); @@ -2693,10 +2692,10 @@ namespace ts { } } - let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); function getValidSourceFile(fileName: string): SourceFile { - let sourceFile = program.getSourceFile(fileName); + const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); } @@ -2716,7 +2715,7 @@ namespace ts { function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { - let hostProjectVersion = host.getProjectVersion(); + const hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion) { return; @@ -2740,17 +2739,17 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - let oldSettings = program && program.getCompilerOptions(); - let newSettings = hostCache.compilationSettings(); - let changesInCompilationSettingsAffectSyntax = oldSettings && + const oldSettings = program && program.getCompilerOptions(); + const newSettings = hostCache.compilationSettings(); + const changesInCompilationSettingsAffectSyntax = oldSettings && (oldSettings.target !== newSettings.target || oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || + oldSettings.jsx !== newSettings.jsx || oldSettings.allowJs !== newSettings.allowJs); // Now create a new compiler - let compilerHost: CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, getCancellationToken: () => cancellationToken, getCanonicalFileName, @@ -2766,22 +2765,22 @@ namespace ts { }, readFile: (fileName): string => { // stub missing host functionality - let entry = hostCache.getOrCreateEntry(fileName); + const entry = hostCache.getOrCreateEntry(fileName); return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); } }; if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile) + compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); } - let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); // Release any files we have acquired in the old program but are // not part of the new program. if (program) { - let oldSourceFiles = program.getSourceFiles(); - for (let oldSourceFile of oldSourceFiles) { + const oldSourceFiles = program.getSourceFiles(); + for (const oldSourceFile of oldSourceFiles) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings); } @@ -2804,7 +2803,7 @@ namespace ts { // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. - let hostFileInformation = hostCache.getOrCreateEntry(fileName); + const hostFileInformation = hostCache.getOrCreateEntry(fileName); if (!hostFileInformation) { return undefined; } @@ -2814,7 +2813,7 @@ namespace ts { // can not be reused. we have to dump all syntax trees and create new ones. if (!changesInCompilationSettingsAffectSyntax) { // Check if the old program had this file already - let oldSourceFile = program && program.getSourceFile(fileName); + const oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to @@ -2851,7 +2850,7 @@ namespace ts { if (!sourceFile) { return false; } - let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + const path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); return sourceFile.version === hostCache.getVersion(path); } @@ -2862,13 +2861,13 @@ namespace ts { } // If number of files in the program do not match, it is not up-to-date - let rootFileNames = hostCache.getRootFileNames(); + const rootFileNames = hostCache.getRootFileNames(); if (program.getSourceFiles().length !== rootFileNames.length) { return false; } // If any file is not up-to-date, then the whole program is not up-to-date - for (let fileName of rootFileNames) { + for (const fileName of rootFileNames) { if (!sourceFileUpToDate(program.getSourceFile(fileName))) { return false; } @@ -2910,18 +2909,18 @@ namespace ts { function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); - let targetSourceFile = getValidSourceFile(fileName); + const targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. - let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics; } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return concatenate(semanticDiagnostics, declarationDiagnostics); } @@ -2937,14 +2936,14 @@ namespace ts { * @return undefined if the name is of external module otherwise a name with striped of any quote */ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, location: Node): string { - let displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); + const displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); if (displayName) { - let firstCharCode = displayName.charCodeAt(0); + const firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there) + // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) return undefined; } } @@ -2987,20 +2986,20 @@ namespace ts { } function getCompletionData(fileName: string, position: number) { - let typeChecker = program.getTypeChecker(); - let syntacticStart = new Date().getTime(); - let sourceFile = getValidSourceFile(fileName); - let isJavaScriptFile = isSourceFileJavaScript(sourceFile); + const typeChecker = program.getTypeChecker(); + const syntacticStart = new Date().getTime(); + const sourceFile = getValidSourceFile(fileName); + const isJavaScriptFile = isSourceFileJavaScript(sourceFile); let isJsDocTagName = false; let start = new Date().getTime(); - let currentToken = getTokenAtPosition(sourceFile, position); + const currentToken = getTokenAtPosition(sourceFile, position); log("getCompletionData: Get current token: " + (new Date().getTime() - start)); start = new Date().getTime(); // Completion not allowed inside comments, bail out if this is the case - let insideComment = isInsideComment(sourceFile, currentToken, position); + const insideComment = isInsideComment(sourceFile, currentToken, position); log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { @@ -3014,7 +3013,7 @@ namespace ts { // /** @type {number | string} */ // Completion should work in the brackets let insideJsDocTagExpression = false; - let tag = getJsDocTagAtPosition(sourceFile, position); + const tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { isJsDocTagName = true; @@ -3024,7 +3023,7 @@ namespace ts { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocReturnTag: - let tagWithExpression = tag; + const tagWithExpression = tag; if (tagWithExpression.typeExpression) { insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; } @@ -3045,7 +3044,7 @@ namespace ts { } start = new Date().getTime(); - let previousToken = findPrecedingToken(position, sourceFile); + const previousToken = findPrecedingToken(position, sourceFile); log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -3055,7 +3054,7 @@ namespace ts { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { - let start = new Date().getTime(); + const start = new Date().getTime(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start)); } @@ -3076,7 +3075,7 @@ namespace ts { return undefined; } - let { parent, kind } = contextToken; + const { parent, kind } = contextToken; if (kind === SyntaxKind.DotToken) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { node = (contextToken.parent).expression; @@ -3103,7 +3102,7 @@ namespace ts { } } - let semanticStart = new Date().getTime(); + const semanticStart = new Date().getTime(); let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; let symbols: Symbol[] = []; @@ -3112,7 +3111,7 @@ namespace ts { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - let tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value))); } @@ -3123,7 +3122,7 @@ namespace ts { isNewIdentifierLocation = false; } else if (isStartingCloseTag) { - let tagName = (contextToken.parent.parent).openingElement.tagName; + const tagName = (contextToken.parent.parent).openingElement.tagName; symbols = [typeChecker.getSymbolAtLocation(tagName)]; isMemberCompletion = true; @@ -3157,7 +3156,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members - let exportedSymbols = typeChecker.getExportsOfModule(symbol); + const exportedSymbols = typeChecker.getExportsOfModule(symbol); forEach(exportedSymbols, symbol => { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); @@ -3166,14 +3165,14 @@ namespace ts { } } - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); addTypeProperties(type); } function addTypeProperties(type: Type) { if (type) { // Filter private properties - for (let symbol of type.getApparentProperties()) { + for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } @@ -3185,8 +3184,8 @@ namespace ts { // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - let unionType = type; - for (let elementType of unionType.types) { + const unionType = type; + for (const elementType of unionType.types) { addTypeProperties(elementType); } } @@ -3256,14 +3255,14 @@ namespace ts { // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - let adjustedPosition = previousToken !== contextToken ? + const adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; - let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context - let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); return true; @@ -3282,8 +3281,8 @@ namespace ts { } function isCompletionListBlocker(contextToken: Node): boolean { - let start = new Date().getTime(); - let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + const start = new Date().getTime(); + const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken); @@ -3310,27 +3309,27 @@ namespace ts { function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { - let containingNodeKind = previousToken.parent.kind; + const containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.CallExpression // func( a, | || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ || containingNodeKind === SyntaxKind.NewExpression // new C(a, | || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === SyntaxKind.BinaryExpression // let x = (a, | + || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list| case SyntaxKind.OpenParenToken: return containingNodeKind === SyntaxKind.CallExpression // func( | || containingNodeKind === SyntaxKind.Constructor // constructor( | || containingNodeKind === SyntaxKind.NewExpression // new C(a| - || containingNodeKind === SyntaxKind.ParenthesizedExpression // let x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ case SyntaxKind.OpenBracketToken: return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === SyntaxKind.ComputedPropertyName // [ | /* this can become an index signature */ + || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ case SyntaxKind.ModuleKeyword: // module | case SyntaxKind.NamespaceKeyword: // namespace | @@ -3343,7 +3342,7 @@ namespace ts { return containingNodeKind === SyntaxKind.ClassDeclaration; // class A{ | case SyntaxKind.EqualsToken: - return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a| + return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| case SyntaxKind.TemplateHead: @@ -3375,8 +3374,8 @@ namespace ts { || contextToken.kind === SyntaxKind.StringLiteralType || contextToken.kind === SyntaxKind.RegularExpressionLiteral || isTemplateLiteralKind(contextToken.kind)) { - let start = contextToken.getStart(); - let end = contextToken.getEnd(); + const start = contextToken.getStart(); + const end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. @@ -3420,7 +3419,7 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); if (isVariableLike(rootDeclaration)) { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -3431,7 +3430,7 @@ namespace ts { } } else { - Debug.fail("Root declaration is not variable-like.") + Debug.fail("Root declaration is not variable-like."); } } else { @@ -3442,7 +3441,7 @@ namespace ts { return false; } - let typeMembers = typeChecker.getPropertiesOfType(typeForObject); + const typeMembers = typeChecker.getPropertiesOfType(typeForObject); if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, existingMembers); @@ -3466,11 +3465,11 @@ namespace ts { * @returns true if 'symbols' was successfully populated; false otherwise. */ function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { - let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? SyntaxKind.ImportDeclaration : SyntaxKind.ExportDeclaration; - let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); - let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + const importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + const moduleSpecifier = importOrExportDeclaration.moduleSpecifier; if (!moduleSpecifier) { return false; @@ -3480,7 +3479,7 @@ namespace ts { isNewIdentifierLocation = false; let exports: Symbol[]; - let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); if (moduleSpecifierSymbol) { exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } @@ -3497,9 +3496,9 @@ namespace ts { function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { if (contextToken) { switch (contextToken.kind) { - case SyntaxKind.OpenBraceToken: // let x = { | - case SyntaxKind.CommaToken: // let x = { a: 0, | - let parent = contextToken.parent; + case SyntaxKind.OpenBraceToken: // const x = { | + case SyntaxKind.CommaToken: // const x = { a: 0, | + const parent = contextToken.parent; if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { return parent; } @@ -3532,8 +3531,8 @@ namespace ts { function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { - let parent = contextToken.parent; - switch(contextToken.kind) { + const parent = contextToken.parent; + switch (contextToken.kind) { case SyntaxKind.LessThanSlashToken: case SyntaxKind.SlashToken: case SyntaxKind.Identifier: @@ -3596,7 +3595,7 @@ namespace ts { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - let containingNodeKind = contextToken.parent.kind; + const containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -3626,13 +3625,13 @@ namespace ts { case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { | containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface a { | - containingNodeKind === SyntaxKind.TypeLiteral; // let x : { | + containingNodeKind === SyntaxKind.TypeLiteral; // const x : { | case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && contextToken.parent && contextToken.parent.parent && (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // let x : { a; | + contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -3699,7 +3698,7 @@ namespace ts { function isDotOfNumericLiteral(contextToken: Node): boolean { if (contextToken.kind === SyntaxKind.NumericLiteral) { - let text = contextToken.getFullText(); + const text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3716,15 +3715,15 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - let exisingImportsOrExports: Map = {}; + const exisingImportsOrExports: Map = {}; - for (let element of namedImportsOrExports) { + for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out if (element.getStart() <= position && position <= element.getEnd()) { continue; } - let name = element.propertyName || element.name; + const name = element.propertyName || element.name; exisingImportsOrExports[name.text] = true; } @@ -3746,8 +3745,8 @@ namespace ts { return contextualMemberSymbols; } - let existingMemberNames: Map = {}; - for (let m of existingMembers) { + const existingMemberNames: Map = {}; + for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment && @@ -3766,7 +3765,7 @@ namespace ts { if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).text + existingName = ((m).propertyName).text; } } else { @@ -3789,8 +3788,8 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - let seenNames: Map = {}; - for (let attr of attributes) { + const seenNames: Map = {}; + for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { continue; @@ -3809,21 +3808,21 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (!completionData) { return undefined; } - let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; + const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let entries: CompletionEntry[] = []; + const entries: CompletionEntry[] = []; if (isRightOfDot && isSourceFileJavaScript(sourceFile)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); @@ -3845,16 +3844,16 @@ namespace ts { return { isMemberCompletion, isNewIdentifierLocation, entries }; function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map): CompletionEntry[] { - let entries: CompletionEntry[] = []; - let target = program.getCompilerOptions().target; + const entries: CompletionEntry[] = []; + const target = program.getCompilerOptions().target; - let nameTable = getNameTable(sourceFile); - for (let name in nameTable) { + const nameTable = getNameTable(sourceFile); + for (const name in nameTable) { if (!uniqueNames[name]) { uniqueNames[name] = name; - let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true); + const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true); if (displayName) { - let entry = { + const entry = { name: displayName, kind: ScriptElementKind.warning, kindModifiers: "", @@ -3875,7 +3874,7 @@ namespace ts { kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - } + }; })); } @@ -3883,7 +3882,7 @@ namespace ts { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true, location); + const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location); if (!displayName) { return undefined; } @@ -3905,13 +3904,13 @@ namespace ts { } function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map { - let start = new Date().getTime(); - let uniqueNames: Map = {}; + const start = new Date().getTime(); + const uniqueNames: Map = {}; if (symbols) { - for (let symbol of symbols) { - let entry = createCompletionEntry(symbol, location); + for (const symbol of symbols) { + const entry = createCompletionEntry(symbol, location); if (entry) { - let id = escapeIdentifier(entry.name); + const id = escapeIdentifier(entry.name); if (!lookUp(uniqueNames, id)) { entries.push(entry); uniqueNames[id] = id; @@ -3929,19 +3928,19 @@ namespace ts { synchronizeHostData(); // Compute all the completion symbols again. - let completionData = getCompletionData(fileName, position); + const completionData = getCompletionData(fileName, position); if (completionData) { - let { symbols, location } = completionData; + const { symbols, location } = completionData; // Find the symbol with the matching entry name. - let target = program.getCompilerOptions().target; + const target = program.getCompilerOptions().target; // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false, location) === entryName ? s : undefined); + const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined); if (symbol) { - let { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); + const { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); return { name: entryName, kindModifiers: getSymbolModifiers(symbol), @@ -3953,7 +3952,7 @@ namespace ts { } // Didn't find a symbol with this name. See if we can find a keyword instead. - let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); + const keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); if (keywordCompletion) { return { name: entryName, @@ -3969,7 +3968,7 @@ namespace ts { // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(symbol: Symbol, location: Node): string { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; @@ -3978,7 +3977,7 @@ namespace ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); + const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -3990,7 +3989,7 @@ namespace ts { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; @@ -4019,8 +4018,8 @@ namespace ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { - let rootSymbolFlags = rootSymbol.getFlags(); + const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + const rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { return ScriptElementKind.memberVariableElement; } @@ -4028,8 +4027,8 @@ namespace ts { }); if (!unionPropertyKind) { // If this was union of all methods, - //make sure it has call signatures before we can label it as method - let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + // make sure it has call signatures before we can label it as method + const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -4053,11 +4052,11 @@ namespace ts { function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning = getMeaningFromLocation(location)) { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let displayParts: SymbolDisplayPart[] = []; + const displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[]; - let symbolFlags = symbol.flags; + const symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; let type: Type; @@ -4073,7 +4072,7 @@ namespace ts { type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - let right = (location.parent).name; + const right = (location.parent).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -4090,15 +4089,15 @@ namespace ts { } if (callExpression) { - let candidateSignatures: Signature[] = []; + const candidateSignatures: Signature[] = []; signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); if (!signature && candidateSignatures.length) { // Use the first candidate: signature = candidateSignatures[0]; } - let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; - let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; + const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -4156,8 +4155,8 @@ namespace ts { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - let functionDeclaration = location.parent; - let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + const functionDeclaration = location.parent; + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4226,8 +4225,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - let declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); - let isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); addFullSymbolName(symbol); @@ -4279,9 +4278,9 @@ namespace ts { } if (symbolFlags & SymbolFlags.EnumMember) { addPrefixForAnyFunctionOrVar(symbol, "enum member"); - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { - let constantValue = typeChecker.getConstantValue(declaration); + const constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4297,7 +4296,7 @@ namespace ts { addFullSymbolName(symbol); ts.forEach(symbol.declarations, declaration => { if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { - let importEqualsDeclaration = declaration; + const importEqualsDeclaration = declaration; if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4308,7 +4307,7 @@ namespace ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4332,7 +4331,7 @@ namespace ts { displayParts.push(spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4347,7 +4346,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - let allSignatures = type.getCallSignatures(); + const allSignatures = type.getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } @@ -4370,7 +4369,7 @@ namespace ts { } function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) { - let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); addRange(displayParts, fullSymbolDisplayParts); } @@ -4416,7 +4415,7 @@ namespace ts { } function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { - let typeParameterParts = mapToDisplayParts(writer => { + const typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4426,8 +4425,8 @@ namespace ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const sourceFile = getValidSourceFile(fileName); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -4436,8 +4435,8 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const typeChecker = program.getTypeChecker(); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { // Try getting just type at this position and show @@ -4449,7 +4448,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - let type = typeChecker.getTypeAtLocation(node); + const type = typeChecker.getTypeAtLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -4464,7 +4463,7 @@ namespace ts { return undefined; } - let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); + const displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), @@ -4486,13 +4485,13 @@ namespace ts { } function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { - let typeChecker = program.getTypeChecker(); - let result: DefinitionInfo[] = []; - let declarations = symbol.getDeclarations(); - let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - let symbolKind = getSymbolKind(symbol, node); - let containerSymbol = symbol.parent; - let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + const typeChecker = program.getTypeChecker(); + const result: DefinitionInfo[] = []; + const declarations = symbol.getDeclarations(); + const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol + const symbolKind = getSymbolKind(symbol, node); + const containerSymbol = symbol.parent; + const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -4510,7 +4509,7 @@ namespace ts { if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { // Find the first class-like declaration and try to get the construct signature. - for (let declaration of symbol.getDeclarations()) { + for (const declaration of symbol.getDeclarations()) { if (isClassLike(declaration)) { return tryAddSignature(declaration.members, /*selectConstructors*/ true, @@ -4535,7 +4534,7 @@ namespace ts { } function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - let declarations: Declaration[] = []; + const declarations: Declaration[] = []; let definition: Declaration; forEach(signatureDeclarations, d => { @@ -4563,24 +4562,24 @@ namespace ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } // Labels if (isJumpStatementTarget(node)) { - let labelName = (node).text; - let label = getTargetLabel((node.parent), (node).text); + const labelName = (node).text; + const label = getTargetLabel((node.parent), (node).text); return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments - let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); + const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); if (comment) { - let referenceFile = tryResolveScriptReference(program, sourceFile, comment); + const referenceFile = tryResolveScriptReference(program, sourceFile, comment); if (referenceFile) { return [{ fileName: referenceFile.fileName, @@ -4594,7 +4593,7 @@ namespace ts { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, @@ -4608,7 +4607,7 @@ namespace ts { // import {A, B} from "mod"; // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { - let declaration = symbol.declarations[0]; + const declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { symbol = typeChecker.getAliasedSymbol(symbol); } @@ -4620,15 +4619,15 @@ namespace ts { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); if (!shorthandSymbol) { return []; } - let shorthandDeclarations = shorthandSymbol.getDeclarations(); - let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); - let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + const shorthandDeclarations = shorthandSymbol.getDeclarations(); + const shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); + const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); + const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -4640,27 +4639,27 @@ namespace ts { function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; } - let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); if (!type) { return undefined; } if (type.flags & TypeFlags.Union) { - let result: DefinitionInfo[] = []; + const result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); @@ -4680,7 +4679,7 @@ namespace ts { let results = getOccurrencesAtPositionCore(fileName, position); if (results) { - let sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); + const sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); // Get occurrences only supports reporting occurrences for the file queried. So // filter down to that list. @@ -4694,10 +4693,10 @@ namespace ts { synchronizeHostData(); filesToSearch = map(filesToSearch, normalizeSlashes); - let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); - let sourceFile = getValidSourceFile(fileName); + const sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -4705,8 +4704,8 @@ namespace ts { return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); function getHighlightSpanForNode(node: Node): HighlightSpan { - let start = node.getStart(); - let end = node.getEnd(); + const start = node.getStart(); + const end = node.getEnd(); return { fileName: sourceFile.fileName, @@ -4723,7 +4722,7 @@ namespace ts { isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - let referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); return convertReferencedSymbols(referencedSymbols); } @@ -4734,11 +4733,11 @@ namespace ts { return undefined; } - let fileNameToDocumentHighlights: Map = {}; - let result: DocumentHighlights[] = []; - for (let referencedSymbol of referencedSymbols) { - for (let referenceEntry of referencedSymbol.references) { - let fileName = referenceEntry.fileName; + const fileNameToDocumentHighlights: Map = {}; + const result: DocumentHighlights[] = []; + for (const referencedSymbol of referencedSymbols) { + for (const referenceEntry of referencedSymbol.references) { + const fileName = referenceEntry.fileName; let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName); if (!documentHighlights) { documentHighlights = { fileName, highlightSpans: [] }; @@ -4759,9 +4758,9 @@ namespace ts { } function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] { - let fileName = sourceFile.fileName; + const fileName = sourceFile.fileName; - let highlightSpans = getHighlightSpans(node); + const highlightSpans = getHighlightSpans(node); if (!highlightSpans || highlightSpans.length === 0) { return undefined; } @@ -4865,7 +4864,7 @@ namespace ts { * into function boundaries and try-blocks with catch-clauses. */ function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] { - let statementAccumulator: ThrowStatement[] = [] + const statementAccumulator: ThrowStatement[] = []; aggregate(node); return statementAccumulator; @@ -4874,7 +4873,7 @@ namespace ts { statementAccumulator.push(node); } else if (node.kind === SyntaxKind.TryStatement) { - let tryStatement = node; + const tryStatement = node; if (tryStatement.catchClause) { aggregate(tryStatement.catchClause); @@ -4905,7 +4904,7 @@ namespace ts { let child: Node = throwStatement; while (child.parent) { - let parent = child.parent; + const parent = child.parent; if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; @@ -4914,7 +4913,7 @@ namespace ts { // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. if (parent.kind === SyntaxKind.TryStatement) { - let tryStatement = parent; + const tryStatement = parent; if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; @@ -4928,7 +4927,7 @@ namespace ts { } function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] { - let statementAccumulator: BreakOrContinueStatement[] = [] + const statementAccumulator: BreakOrContinueStatement[] = []; aggregate(node); return statementAccumulator; @@ -4944,7 +4943,7 @@ namespace ts { } function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { - let actualOwner = getBreakOrContinueOwner(statement); + const actualOwner = getBreakOrContinueOwner(statement); return actualOwner && actualOwner === owner; } @@ -4979,7 +4978,7 @@ namespace ts { } function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] { - let container = declaration.parent; + const container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { @@ -5009,8 +5008,8 @@ namespace ts { return undefined; } - let keywords: Node[] = []; - let modifierFlag: NodeFlags = getFlagFromModifier(modifier); + const keywords: Node[] = []; + const modifierFlag: NodeFlags = getFlagFromModifier(modifier); let nodes: Node[]; switch (container.kind) { @@ -5035,7 +5034,7 @@ namespace ts { // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - let constructor = forEach((container).members, member => { + const constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -5048,7 +5047,7 @@ namespace ts { } break; default: - Debug.fail("Invalid container kind.") + Debug.fail("Invalid container kind."); } forEach(nodes, node => { @@ -5091,7 +5090,7 @@ namespace ts { } function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor); tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor); @@ -5099,7 +5098,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void { - let accessor = getDeclarationOfKind(accessorSymbol, accessorKind); + const accessor = getDeclarationOfKind(accessorSymbol, accessorKind); if (accessor) { forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword)); @@ -5108,9 +5107,9 @@ namespace ts { } function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] { - let declarations = constructorDeclaration.symbol.getDeclarations() + const declarations = constructorDeclaration.symbol.getDeclarations(); - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(declarations, declaration => { forEach(declaration.getChildren(), token => { @@ -5122,12 +5121,12 @@ namespace ts { } function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { - let loopTokens = loopNode.getChildren(); + const loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { @@ -5137,7 +5136,7 @@ namespace ts { } } - let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { @@ -5149,7 +5148,7 @@ namespace ts { } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { - let owner = getBreakOrContinueOwner(breakOrContinueStatement); + const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { @@ -5158,7 +5157,7 @@ namespace ts { case SyntaxKind.ForOfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner) + return getLoopBreakContinueOccurrences(owner); case SyntaxKind.SwitchStatement: return getSwitchCaseDefaultOccurrences(owner); @@ -5169,7 +5168,7 @@ namespace ts { } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -5177,7 +5176,7 @@ namespace ts { forEach(switchStatement.caseBlock.clauses, clause => { pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + const breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { @@ -5190,7 +5189,7 @@ namespace ts { } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); @@ -5199,7 +5198,7 @@ namespace ts { } if (tryStatement.finallyBlock) { - let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } @@ -5207,13 +5206,13 @@ namespace ts { } function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] { - let owner = getThrowStatementOwner(throwStatement); + const owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - let keywords: Node[] = []; + const keywords: Node[] = []; forEach(aggregateOwnedThrowStatements(owner), throwStatement => { pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword); @@ -5231,14 +5230,14 @@ namespace ts { } function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] { - let func = getContainingFunction(returnStatement); + const func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } - let keywords: Node[] = [] + const keywords: Node[] = []; forEachReturnStatement(func.body, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -5252,7 +5251,7 @@ namespace ts { } function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] { - let keywords: Node[] = []; + const keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (ifStatement.parent).elseStatement === ifStatement) { @@ -5261,7 +5260,7 @@ namespace ts { // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (ifStatement) { - let children = ifStatement.getChildren(); + const children = ifStatement.getChildren(); pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. @@ -5272,20 +5271,20 @@ namespace ts { } if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) { - break + break; } ifStatement = ifStatement.elseStatement; } - let result: HighlightSpan[] = []; + const result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { - let elseKeyword = keywords[i]; - let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + const elseKeyword = keywords[i]; + const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. let shouldCombindElseAndIf = true; @@ -5328,9 +5327,9 @@ namespace ts { return undefined; } - let result: ReferenceEntry[] = []; - for (let entry of documentHighlights) { - for (let highlightSpan of entry.highlightSpans) { + const result: ReferenceEntry[] = []; + for (const entry of documentHighlights) { + for (const highlightSpan of entry.highlightSpans) { result.push({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -5348,9 +5347,9 @@ namespace ts { return undefined; } - let referenceEntries: ReferenceEntry[] = []; + const referenceEntries: ReferenceEntry[] = []; - for (let referenceSymbol of referenceSymbols) { + for (const referenceSymbol of referenceSymbols) { addRange(referenceEntries, referenceSymbol.references); } @@ -5358,17 +5357,17 @@ namespace ts { } function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - let referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + const referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number): ReferencedSymbol[]{ - let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + function findReferences(fileName: string, position: number): ReferencedSymbol[] { + const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); @@ -5377,17 +5376,17 @@ namespace ts { function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); - let node = getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } if (node.kind !== SyntaxKind.Identifier && // TODO (drosen): This should be enabled in a later release - currently breaks rename. - //node.kind !== SyntaxKind.ThisKeyword && - //node.kind !== SyntaxKind.SuperKeyword && + // node.kind !== SyntaxKind.ThisKeyword && + // node.kind !== SyntaxKind.SuperKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -5398,12 +5397,12 @@ namespace ts { } function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { - let typeChecker = program.getTypeChecker(); + const typeChecker = program.getTypeChecker(); // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - let labelDefinition = getTargetLabel((node.parent), (node).text); + const labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; @@ -5422,7 +5421,7 @@ namespace ts { return getReferencesForSuperKeyword(node); } - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -5430,7 +5429,7 @@ namespace ts { return undefined; } - let declarations = symbol.declarations; + const declarations = symbol.declarations; // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!declarations || !declarations.length) { @@ -5440,29 +5439,29 @@ namespace ts { let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references - let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); + const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - let declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). - let scope = getSymbolScope(symbol); + const scope = getSymbolScope(symbol); // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - let symbolToIndex: number[] = []; + const symbolToIndex: number[] = []; if (scope) { result = []; getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - let internedName = getInternedName(symbol, node, declarations) - for (let sourceFile of sourceFiles) { + const internedName = getInternedName(symbol, node, declarations); + for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - let nameTable = getNameTable(sourceFile); + const nameTable = getNameTable(sourceFile); if (lookUp(nameTable, internedName)) { result = result || []; @@ -5474,9 +5473,9 @@ namespace ts { return result; function getDefinition(symbol: Symbol): DefinitionInfo { - let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - let name = map(info.displayParts, p => p.text).join(""); - let declarations = symbol.declarations; + const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); + const name = map(info.displayParts, p => p.text).join(""); + const declarations = symbol.declarations; if (!declarations || declarations.length === 0) { return undefined; } @@ -5506,7 +5505,7 @@ namespace ts { // Try to get the local symbol if we're dealing with an 'export default' // since that symbol has the "true" name. - let localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); + const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); symbol = localExportDefaultSymbol || symbol; return stripQuotes(symbol.name); @@ -5523,14 +5522,14 @@ namespace ts { function getSymbolScope(symbol: Symbol): Node { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. - let valueDeclaration = symbol.valueDeclaration; + const valueDeclaration = symbol.valueDeclaration; if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } // If this is private property or method, the scope is the containing class if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { - let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); + const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -5548,12 +5547,12 @@ namespace ts { return undefined; } - let scope: Node = undefined; + let scope: Node; - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations) { - for (let declaration of declarations) { - let container = getContainerNode(declaration); + for (const declaration of declarations) { + const container = getContainerNode(declaration); if (!container) { return undefined; @@ -5579,7 +5578,7 @@ namespace ts { } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] { - let positions: number[] = []; + const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search // Also, need to make this work for unicode escapes. @@ -5589,9 +5588,9 @@ namespace ts { return positions; } - let text = sourceFile.text; - let sourceLength = text.length; - let symbolNameLength = symbolName.length; + const text = sourceFile.text; + const sourceLength = text.length; + const symbolNameLength = symbolName.length; let position = text.indexOf(symbolName, start); while (position >= 0) { @@ -5602,7 +5601,7 @@ namespace ts { // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). - let endPosition = position + symbolNameLength; + const endPosition = position + symbolNameLength; if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { @@ -5616,14 +5615,14 @@ namespace ts { } function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { - let references: ReferenceEntry[] = []; - let sourceFile = container.getSourceFile(); - let labelName = targetLabel.text; - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + const references: ReferenceEntry[] = []; + const sourceFile = container.getSourceFile(); + const labelName = targetLabel.text; + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -5635,14 +5634,14 @@ namespace ts { } }); - let definition: DefinitionInfo = { + const definition: DefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) - } + }; return [{ definition, references }]; } @@ -5687,19 +5686,19 @@ namespace ts { result: ReferencedSymbol[], symbolToIndex: number[]): void { - let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* { cancellationToken.throwIfCancellationRequested(); - let referenceLocation = getTouchingPropertyName(sourceFile, position); + const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking @@ -5727,14 +5726,14 @@ namespace ts { return; } - let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); if (referenceSymbol) { - let referenceSymbolDeclaration = referenceSymbol.valueDeclaration; - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - let relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); if (relatedSymbol) { - let referencedSymbol = getReferencedSymbol(relatedSymbol); + const referencedSymbol = getReferencedSymbol(relatedSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation)); } /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment @@ -5744,7 +5743,7 @@ namespace ts { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) { - let referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } @@ -5754,7 +5753,7 @@ namespace ts { return; function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { - let symbolId = getSymbolId(symbol); + const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { index = result.length; @@ -5773,7 +5772,7 @@ namespace ts { return isInCommentHelper(sourceFile, position, isNonReferenceComment); function isNonReferenceComment(c: CommentRange): boolean { - let commentText = sourceFile.text.substring(c.pos, c.end); + const commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); } } @@ -5802,20 +5801,20 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; - let sourceFile = searchSpaceNode.getSourceFile(); - let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + const sourceFile = searchSpaceNode.getSourceFile(); + const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; } - let container = getSuperContainer(node, /*includeFunctions*/ false); + const container = getSuperContainer(node, /*includeFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space @@ -5825,7 +5824,7 @@ namespace ts { } }); - let definition = getDefinition(searchSpaceNode.symbol); + const definition = getDefinition(searchSpaceNode.symbol); return [{ definition, references }]; } @@ -5847,7 +5846,7 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - staticFlag &= searchSpaceNode.flags + staticFlag &= searchSpaceNode.flags; searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case SyntaxKind.SourceFile: @@ -5864,7 +5863,7 @@ namespace ts { return undefined; } - let references: ReferenceEntry[] = []; + const references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -5874,7 +5873,7 @@ namespace ts { }); } else { - let sourceFile = searchSpaceNode.getSourceFile(); + const sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } @@ -5895,12 +5894,12 @@ namespace ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); if (!node || (node.kind !== SyntaxKind.ThisKeyword && node.kind !== SyntaxKind.ThisType)) { return; } - let container = getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: @@ -5935,7 +5934,7 @@ namespace ts { function populateSearchSymbolSet(symbol: Symbol, location: Node): Symbol[] { // The search set contains at least the current symbol - let result = [symbol]; + const result = [symbol]; // If the symbol is an alias, add what it alaises to the list if (isImportOrExportSpecifierImportSymbol(symbol)) { @@ -5955,13 +5954,13 @@ namespace ts { * property name and variable declaration of the identifier. * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service * should show both 'name' in 'obj' and 'name' in variable declaration - * let name = "Foo"; - * let obj = { name }; + * const name = "Foo"; + * const obj = { name }; * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration * will be included correctly. */ - let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); if (shorthandValueSymbol) { result.push(shorthandValueSymbol); } @@ -5999,9 +5998,9 @@ namespace ts { function getPropertySymbolFromTypeReference(typeReference: ExpressionWithTypeArguments) { if (typeReference) { - let type = typeChecker.getTypeAtLocation(typeReference); + const type = typeChecker.getTypeAtLocation(typeReference); if (type) { - let propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + const propertySymbol = typeChecker.getPropertyOfType(type, propertyName); if (propertySymbol) { result.push(propertySymbol); } @@ -6021,7 +6020,7 @@ namespace ts { // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { - let aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); + const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); if (searchSymbols.indexOf(aliasedSymbol) >= 0) { return aliasedSymbol; } @@ -6047,7 +6046,7 @@ namespace ts { // Finally, try all properties with the same name in any type the containing type extended or implemented, and // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - let result: Symbol[] = []; + const result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } @@ -6058,21 +6057,21 @@ namespace ts { function getPropertySymbolsFromContextualType(node: Node): Symbol[] { if (isNameOfPropertyAssignment(node)) { - let objectLiteral = node.parent.parent; - let contextualType = typeChecker.getContextualType(objectLiteral); - let name = (node).text; + const objectLiteral = node.parent.parent; + const contextualType = typeChecker.getContextualType(objectLiteral); + const name = (node).text; if (contextualType) { if (contextualType.flags & TypeFlags.Union) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - let unionProperty = contextualType.getProperty(name) + const unionProperty = contextualType.getProperty(name); if (unionProperty) { return [unionProperty]; } else { - let result: Symbol[] = []; + const result: Symbol[] = []; forEach((contextualType).types, t => { - let symbol = t.getProperty(name); + const symbol = t.getProperty(name); if (symbol) { result.push(symbol); } @@ -6081,7 +6080,7 @@ namespace ts { } } else { - let symbol = contextualType.getProperty(name); + const symbol = contextualType.getProperty(name); if (symbol) { return [symbol]; } @@ -6110,8 +6109,8 @@ namespace ts { // Remember the last meaning lastIterationMeaning = meaning; - for (let declaration of declarations) { - let declarationMeaning = getMeaningFromDeclaration(declaration); + for (const declaration of declarations) { + const declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -6146,13 +6145,13 @@ namespace ts { return true; } - let parent = node.parent; + const parent = node.parent; if (parent) { if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { return true; } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - let operator = (parent).operatorToken.kind; + const operator = (parent).operatorToken.kind; return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } @@ -6174,8 +6173,8 @@ namespace ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let outputFiles: OutputFile[] = []; + const sourceFile = getValidSourceFile(fileName); + const outputFiles: OutputFile[] = []; function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { outputFiles.push({ @@ -6185,7 +6184,7 @@ namespace ts { }); } - let emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + const emitOutput = program.emit(sourceFile, writeFile, cancellationToken); return { outputFiles, @@ -6278,7 +6277,7 @@ namespace ts { } if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { - let decl = root.parent.parent.parent; + const decl = root.parent.parent.parent; return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent).token === SyntaxKind.ImplementsKeyword) || (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent).token === SyntaxKind.ExtendsKeyword); } @@ -6350,7 +6349,7 @@ namespace ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } @@ -6361,10 +6360,10 @@ namespace ts { } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - let node = getTouchingPropertyName(sourceFile, startPos); + const node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -6420,13 +6419,13 @@ namespace ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings()); } @@ -6458,11 +6457,11 @@ namespace ts { function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let result: number[] = []; - let classifiableNames = program.getClassifiableNames(); + const result: number[] = []; + const classifiableNames = program.getClassifiableNames(); processNode(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6474,7 +6473,7 @@ namespace ts { } function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType { - let flags = symbol.getFlags(); + const flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return; } @@ -6522,19 +6521,19 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - let kind = node.kind; + const kind = node.kind; checkForClassificationCancellation(kind); if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { - let identifier = node; + const identifier = node; // Only bother calling into the typechecker if this is an identifier that // could possibly resolve to a type name. This makes classification run // in a third of the time it would normally take. if (classifiableNames[identifier.text]) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - let type = classifySymbol(symbol, getMeaningFromLocation(node)); + const type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { pushClassification(node.getStart(), node.getWidth(), type); } @@ -6574,8 +6573,8 @@ namespace ts { function convertClassifications(classifications: Classifications): ClassifiedSpan[] { Debug.assert(classifications.spans.length % 3 === 0); - let dense = classifications.spans; - let result: ClassifiedSpan[] = []; + const dense = classifications.spans; + const result: ClassifiedSpan[] = []; for (let i = 0, n = dense.length; i < n; i += 3) { result.push({ textSpan: createTextSpan(dense[i], dense[i + 1]), @@ -6592,15 +6591,15 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let spanStart = span.start; - let spanLength = span.length; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const spanStart = span.start; + const spanLength = span.length; // Make a scanner we can get trivia from. - let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); - let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); + const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - let result: number[] = []; + const result: number[] = []; processElement(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6614,15 +6613,15 @@ namespace ts { function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { - let start = triviaScanner.getTextPos(); + const start = triviaScanner.getTextPos(); // only bother scanning if we have something that could be trivia. if (!couldStartTrivia(sourceFile.text, start)) { return start; } - let kind = triviaScanner.scan(); - let end = triviaScanner.getTextPos(); - let width = end - start; + const kind = triviaScanner.scan(); + const end = triviaScanner.getTextPos(); + const width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { @@ -6646,8 +6645,8 @@ namespace ts { } if (kind === SyntaxKind.ConflictMarkerTrivia) { - let text = sourceFile.text; - let ch = text.charCodeAt(start); + const text = sourceFile.text; + const ch = text.charCodeAt(start); // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. @@ -6668,7 +6667,7 @@ namespace ts { if (kind === SyntaxKind.MultiLineCommentTrivia) { // See if this is a doc comment. If so, we'll classify certain portions of it // specially. - let docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); + const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { docCommentAndDiagnostics.jsDocComment.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); @@ -6687,7 +6686,7 @@ namespace ts { function classifyJSDocComment(docComment: JSDocComment) { let pos = docComment.pos; - for (let tag of docComment.tags) { + for (const tag of docComment.tags) { // As we walk through each tag, classify the portion of text from the end of // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { @@ -6745,7 +6744,7 @@ namespace ts { } function processJSDocTemplateTag(tag: JSDocTemplateTag) { - for (let child of tag.getChildren()) { + for (const child of tag.getChildren()) { processElement(child); } } @@ -6767,11 +6766,11 @@ namespace ts { } function classifyDisabledCodeToken() { - let start = mergeConflictScanner.getTextPos(); - let tokenKind = mergeConflictScanner.scan(); - let end = mergeConflictScanner.getTextPos(); + const start = mergeConflictScanner.getTextPos(); + const tokenKind = mergeConflictScanner.scan(); + const end = mergeConflictScanner.getTextPos(); - let type = classifyTokenType(tokenKind); + const type = classifyTokenType(tokenKind); if (type) { pushClassification(start, end - start, type); } @@ -6782,12 +6781,12 @@ namespace ts { return; } - let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - let tokenWidth = token.end - tokenStart; + const tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { - let type = classifyTokenType(token.kind, token); + const type = classifyTokenType(token.kind, token); if (type) { pushClassification(tokenStart, tokenWidth, type); } @@ -6914,9 +6913,9 @@ namespace ts { if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); - let children = element.getChildren(sourceFile); + const children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { - let child = children[i]; + const child = children[i]; if (isToken(child)) { classifyToken(child); } @@ -6931,28 +6930,28 @@ namespace ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - let result: TextSpan[] = []; + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const result: TextSpan[] = []; - let token = getTouchingToken(sourceFile, position); + const token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { - let matchKind = getMatchingTokenKind(token); + const matchKind = getMatchingTokenKind(token); // Ensure that there is a corresponding token to match ours. if (matchKind) { - let parentElement = token.parent; + const parentElement = token.parent; - let childNodes = parentElement.getChildren(sourceFile); - for (let current of childNodes) { + const childNodes = parentElement.getChildren(sourceFile); + for (const current of childNodes) { if (current.kind === matchKind) { - let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start < range2.start) { @@ -6972,11 +6971,11 @@ namespace ts { function getMatchingTokenKind(token: Node): ts.SyntaxKind { switch (token.kind) { - case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken + case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken; case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken; case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken; case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken + case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken; case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken; case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken; case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken; @@ -6988,29 +6987,29 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); - let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start)); return result; } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -7046,16 +7045,16 @@ namespace ts { * be performed. */ function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { - let start = new Date().getTime(); - let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + const start = new Date().getTime(); + const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return undefined; } - let tokenAtPos = getTokenAtPosition(sourceFile, position); - let tokenStart = tokenAtPos.getStart() + const tokenAtPos = getTokenAtPosition(sourceFile, position); + const tokenStart = tokenAtPos.getStart(); if (!tokenAtPos || tokenStart < position) { return undefined; } @@ -7091,11 +7090,11 @@ namespace ts { return undefined; } - let parameters = getParametersForJsDocOwningNode(commentOwner); - let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + const parameters = getParametersForJsDocOwningNode(commentOwner); + const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + const lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; @@ -7119,7 +7118,7 @@ namespace ts { // * if the caret was directly in front of the object, then we add an extra line and indentation. const preamble = "/**" + newLine + indentationStr + " * "; - let result = + const result = preamble + newLine + docParams + indentationStr + " */" + @@ -7163,7 +7162,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return (rightHandSide).parameters; case SyntaxKind.ClassExpression: - for (let member of (rightHandSide).members) { + for (const member of (rightHandSide).members) { if (member.kind === SyntaxKind.Constructor) { return (member).parameters; } @@ -7183,15 +7182,15 @@ namespace ts { // anything away. synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); + const sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); - let fileContents = sourceFile.text; - let result: TodoComment[] = []; + const fileContents = sourceFile.text; + const result: TodoComment[] = []; if (descriptors.length > 0) { - let regExp = getTodoCommentsRegExp(); + const regExp = getTodoCommentsRegExp(); let matchArray: RegExpExecArray; while (matchArray = regExp.exec(fileContents)) { @@ -7214,15 +7213,15 @@ namespace ts { // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. - let firstDescriptorCaptureIndex = 3; + const firstDescriptorCaptureIndex = 3; Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); - let preamble = matchArray[1]; - let matchPosition = matchArray.index + preamble.length; + const preamble = matchArray[1]; + const matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - let token = getTokenAtPosition(sourceFile, matchPosition); + const token = getTokenAtPosition(sourceFile, matchPosition); if (!isInsideComment(sourceFile, token, matchPosition)) { continue; } @@ -7241,7 +7240,7 @@ namespace ts { continue; } - let message = matchArray[2]; + const message = matchArray[2]; result.push({ descriptor: descriptor, message: message, @@ -7272,14 +7271,14 @@ namespace ts { // // The following three regexps are used to match the start of the text up to the TODO // comment portion. - let singleLineCommentStart = /(?:\/\/+\s*)/.source; - let multiLineCommentStart = /(?:\/\*+\s*)/.source; - let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + const singleLineCommentStart = /(?:\/\/+\s*)/.source; + const multiLineCommentStart = /(?:\/\*+\s*)/.source; + const anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + const preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -7289,17 +7288,17 @@ namespace ts { // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). - let endOfLineOrEndOfComment = /(?:$|\*\/)/.source - let messageRemainder = /(?:.*?)/.source + const endOfLineOrEndOfComment = /(?:$|\*\/)/.source; + const messageRemainder = /(?:.*?)/.source; // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. - let messagePortion = "(" + literals + messageRemainder + ")"; - let regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + const messagePortion = "(" + literals + messageRemainder + ")"; + const regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim @@ -7325,40 +7324,40 @@ namespace ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - let sourceFile = getValidSourceFile(fileName); - let typeChecker = program.getTypeChecker(); + const sourceFile = getValidSourceFile(fileName); + const typeChecker = program.getTypeChecker(); - let node = getTouchingWord(sourceFile, position); + const node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - let symbol = typeChecker.getSymbolAtLocation(node); + const symbol = typeChecker.getSymbolAtLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol) { - let declarations = symbol.getDeclarations(); + const declarations = symbol.getDeclarations(); if (declarations && declarations.length > 0) { // Disallow rename for elements that are defined in the standard TypeScript library. - let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); + const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); if (defaultLibFileName) { - for (let current of declarations) { - let sourceFile = current.getSourceFile(); - var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + for (const current of declarations) { + const sourceFile = current.getSourceFile(); + const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) { return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); } } } - let displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - let kind = getSymbolKind(symbol, node); + const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + const kind = getSymbolKind(symbol, node); if (kind) { return { canRename: true, - localizedErrorMessage: undefined, + kind, displayName, + localizedErrorMessage: undefined, fullDisplayName: typeChecker.getFullyQualifiedName(symbol), - kind: kind, kindModifiers: getSymbolModifiers(symbol), triggerSpan: createTextSpan(node.getStart(), node.getWidth()) }; @@ -7425,14 +7424,14 @@ namespace ts { /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { - initializeNameTable(sourceFile) + initializeNameTable(sourceFile); } return sourceFile.nameTable; } function initializeNameTable(sourceFile: SourceFile): void { - let nameTable: Map = {}; + const nameTable: Map = {}; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -7470,13 +7469,13 @@ namespace ts { /// Classifier export function createClassifier(): Classifier { - let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); /// We do not have a full parser support to know when we should parse a regex or not /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - let noRegexTable: boolean[] = []; + const noRegexTable: boolean[] = []; noRegexTable[SyntaxKind.Identifier] = true; noRegexTable[SyntaxKind.StringLiteral] = true; noRegexTable[SyntaxKind.NumericLiteral] = true; @@ -7510,7 +7509,7 @@ namespace ts { // // Where on the second line, you will get the 'return' keyword, // a string literal, and a template end consisting of '} } `'. - let templateStack: SyntaxKind[] = []; + const templateStack: SyntaxKind[] = []; /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { @@ -7536,18 +7535,18 @@ namespace ts { } function convertClassifications(classifications: Classifications, text: string): ClassificationResult { - let entries: ClassificationInfo[] = []; - let dense = classifications.spans; + const entries: ClassificationInfo[] = []; + const dense = classifications.spans; let lastEnd = 0; for (let i = 0, n = dense.length; i < n; i += 3) { - let start = dense[i]; - let length = dense[i + 1]; - let type = dense[i + 2]; + const start = dense[i]; + const length = dense[i + 1]; + const type = dense[i + 2]; // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { - let whitespaceLength = start - lastEnd; + const whitespaceLength = start - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7557,7 +7556,7 @@ namespace ts { lastEnd = start + length; } - let whitespaceLength = text.length - lastEnd; + const whitespaceLength = text.length - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7611,7 +7610,7 @@ namespace ts { // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { case EndOfLineState.InDoubleQuoteStringLiteral: - text = '"\\\n' + text; + text = "\"\\\n" + text; offset = 3; break; case EndOfLineState.InSingleQuoteStringLiteral: @@ -7637,7 +7636,7 @@ namespace ts { scanner.setText(text); - let result: Classifications = { + const result: Classifications = { endOfLineState: EndOfLineState.None, spans: [] }; @@ -7719,7 +7718,7 @@ namespace ts { // If we don't have anything on the template stack, // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { - let lastTemplateStackToken = lastOrUndefined(templateStack); + const lastTemplateStackToken = lastOrUndefined(templateStack); if (lastTemplateStackToken === SyntaxKind.TemplateHead) { token = scanner.reScanTemplateToken(); @@ -7749,17 +7748,17 @@ namespace ts { return result; function processToken(): void { - let start = scanner.getTokenPos(); - let end = scanner.getTextPos(); + const start = scanner.getTokenPos(); + const end = scanner.getTextPos(); addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) { // Check to see if we finished up on a multiline string literal. - let tokenText = scanner.getTokenText(); + const tokenText = scanner.getTokenText(); if (scanner.isUnterminated()) { - let lastCharIndex = tokenText.length - 1; + const lastCharIndex = tokenText.length - 1; let numBackslashes = 0; while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) { @@ -7768,7 +7767,7 @@ namespace ts { // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { - let quoteChar = tokenText.charCodeAt(0); + const quoteChar = tokenText.charCodeAt(0); result.endOfLineState = quoteChar === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; @@ -7817,7 +7816,7 @@ namespace ts { // relative to the original text. start -= offset; end -= offset; - let length = end - start; + const length = end - start; if (length > 0) { result.spans.push(start); @@ -7932,7 +7931,7 @@ namespace ts { } /// getDefaultLibraryFilePath - declare let __dirname: string; + declare const __dirname: string; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript From e3075bab784a6577e354cb96e84f8d061e15a91b Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 15 Dec 2015 10:57:56 -0800 Subject: [PATCH 59/75] Revert linting services --- Jakefile.js | 3 +- src/services/services.ts | 1071 +++++++++++++++++++------------------- 2 files changed, 537 insertions(+), 537 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 91bd805a27b..beb16d2886f 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -924,8 +924,7 @@ function lintFileAsync(options, path, cb) { var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) - .concat(scriptSources) - .concat([path.join(servicesDirectory,"services.ts")]); + .concat(scriptSources); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { diff --git a/src/services/services.ts b/src/services/services.ts index 4109a4eb345..8e2e4913edd 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -12,7 +12,7 @@ namespace ts { /** The version of the language service API */ - export const servicesVersion = "0.4"; + export let servicesVersion = "0.4" export interface Node { getSourceFile(): SourceFile; @@ -48,7 +48,7 @@ namespace ts { getConstructSignatures(): Signature[]; getStringIndexType(): Type; getNumberIndexType(): Type; - getBaseTypes(): ObjectType[]; + getBaseTypes(): ObjectType[] } export interface Signature { @@ -97,7 +97,7 @@ namespace ts { dispose?(): void; } - export namespace ScriptSnapshot { + export module ScriptSnapshot { class StringScriptSnapshot implements IScriptSnapshot { constructor(private text: string) { @@ -126,12 +126,12 @@ namespace ts { referencedFiles: FileReference[]; importedFiles: FileReference[]; ambientExternalModules: string[]; - isLibFile: boolean; + isLibFile: boolean } - const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); + let scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - const emptyArray: any[] = []; + let emptyArray: any[] = []; const jsDocTagNames = [ "augments", @@ -174,7 +174,7 @@ namespace ts { let jsDocCompletionEntries: CompletionEntry[]; function createNode(kind: SyntaxKind, pos: number, end: number, flags: NodeFlags, parent?: Node): NodeObject { - const node = new NodeObject(kind, pos, end); + let node = new NodeObject(kind, pos, end); node.flags = flags; node.parent = parent; return node; @@ -235,8 +235,8 @@ namespace ts { private addSyntheticNodes(nodes: Node[], pos: number, end: number): number { scanner.setTextPos(pos); while (pos < end) { - const token = scanner.scan(); - const textPos = scanner.getTextPos(); + let token = scanner.scan(); + let textPos = scanner.getTextPos(); nodes.push(createNode(token, pos, textPos, NodeFlags.Synthetic, this)); pos = textPos; } @@ -244,11 +244,13 @@ namespace ts { } private createSyntaxList(nodes: NodeArray): Node { - const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); + let list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, NodeFlags.Synthetic, this); list._children = []; let pos = nodes.pos; - for (const node of nodes) { + + + for (let node of nodes) { if (pos < node.pos) { pos = this.addSyntheticNodes(list._children, pos, node.pos); } @@ -267,14 +269,14 @@ namespace ts { scanner.setText((sourceFile || this.getSourceFile()).text); children = []; let pos = this.pos; - const processNode = (node: Node) => { + let processNode = (node: Node) => { if (pos < node.pos) { pos = this.addSyntheticNodes(children, pos, node.pos); } children.push(node); pos = node.end; }; - const processNodes = (nodes: NodeArray) => { + let processNodes = (nodes: NodeArray) => { if (pos < nodes.pos) { pos = this.addSyntheticNodes(children, pos, nodes.pos); } @@ -306,20 +308,20 @@ namespace ts { } public getFirstToken(sourceFile?: SourceFile): Node { - const children = this.getChildren(sourceFile); + let children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - const child = children[0]; + let child = children[0]; return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } public getLastToken(sourceFile?: SourceFile): Node { - const children = this.getChildren(sourceFile); + let children = this.getChildren(sourceFile); - const child = lastOrUndefined(children); + let child = lastOrUndefined(children); if (!child) { return undefined; } @@ -364,8 +366,8 @@ namespace ts { } function getJsDocCommentsFromDeclarations(declarations: Declaration[], name: string, canUseParsedParamTagComments: boolean) { - const documentationComment = []; - const docComments = getJsDocCommentsSeparatedByNewLines(); + let documentationComment = []; + let docComments = getJsDocCommentsSeparatedByNewLines(); ts.forEach(docComments, docComment => { if (documentationComment.length) { documentationComment.push(lineBreakPart()); @@ -376,22 +378,22 @@ namespace ts { return documentationComment; function getJsDocCommentsSeparatedByNewLines() { - const paramTag = "@param"; - const jsDocCommentParts: SymbolDisplayPart[] = []; + let paramTag = "@param"; + let jsDocCommentParts: SymbolDisplayPart[] = []; ts.forEach(declarations, (declaration, indexOfDeclaration) => { // Make sure we are collecting doc comment from declaration once, // In case of union property there might be same declaration multiple times // which only varies in type parameter - // Eg. const a: Array | Array; a.length + // Eg. let a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array if (indexOf(declarations, declaration) === indexOfDeclaration) { - const sourceFileOfDeclaration = getSourceFileOfNode(declaration); + let sourceFileOfDeclaration = getSourceFileOfNode(declaration); // If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) { ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => { - const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + let cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedParamJsDocComment) { addRange(jsDocCommentParts, cleanedParamJsDocComment); } @@ -411,7 +413,7 @@ namespace ts { // Get the cleaned js doc comment text from the declaration ts.forEach(getJsDocCommentTextRange( declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => { - const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); + let cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration); if (cleanedJsDocComment) { addRange(jsDocCommentParts, cleanedJsDocComment); } @@ -437,7 +439,7 @@ namespace ts { } for (; pos < end; pos++) { - const ch = sourceFile.text.charCodeAt(pos); + let ch = sourceFile.text.charCodeAt(pos); if (!isWhiteSpace(ch) || isLineBreak(ch)) { // Either found lineBreak or non whiteSpace return pos; @@ -478,7 +480,7 @@ namespace ts { function getCleanedJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let spacesToRemoveAfterAsterisk: number; - const docComments: SymbolDisplayPart[] = []; + let docComments: SymbolDisplayPart[] = []; let blankLineCount = 0; let isInParamTag = false; @@ -489,7 +491,7 @@ namespace ts { // If the comment starts with '*' consume the spaces on this line if (pos < end && sourceFile.text.charCodeAt(pos) === CharacterCodes.asterisk) { - const lineStartPos = pos + 1; + let lineStartPos = pos + 1; pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, spacesToRemoveAfterAsterisk); // Set the spaces to remove after asterisk as margin if not already set @@ -503,7 +505,7 @@ namespace ts { // Analyse text on this line while (pos < end && !isLineBreak(sourceFile.text.charCodeAt(pos))) { - const ch = sourceFile.text.charAt(pos); + let ch = sourceFile.text.charAt(pos); if (ch === "@") { // If it is @param tag if (isParamTag(pos, end, sourceFile)) { @@ -542,7 +544,7 @@ namespace ts { function getCleanedParamJsDocComment(pos: number, end: number, sourceFile: SourceFile) { let paramHelpStringMargin: number; - const paramDocComments: SymbolDisplayPart[] = []; + let paramDocComments: SymbolDisplayPart[] = []; while (pos < end) { if (isParamTag(pos, end, sourceFile)) { let blankLineCount = 0; @@ -557,7 +559,7 @@ namespace ts { if (sourceFile.text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; for (let curlies = 1; pos < end; pos++) { - const charCode = sourceFile.text.charCodeAt(pos); + let charCode = sourceFile.text.charCodeAt(pos); // { character means we need to find another } to match the found one if (charCode === CharacterCodes.openBrace) { @@ -601,9 +603,9 @@ namespace ts { } let paramHelpString = ""; - const firstLineParamHelpStringPos = pos; + let firstLineParamHelpStringPos = pos; while (pos < end) { - const ch = sourceFile.text.charCodeAt(pos); + let ch = sourceFile.text.charCodeAt(pos); // at line break, set this comment line text and go to next line if (isLineBreak(ch)) { @@ -672,15 +674,15 @@ namespace ts { } // Now consume white spaces max - const startOfLinePos = pos; + let startOfLinePos = pos; pos = consumeWhiteSpacesOnTheLine(pos, end, sourceFile, paramHelpStringMargin); if (pos >= end) { return; } - const consumedSpaces = pos - startOfLinePos; + let consumedSpaces = pos - startOfLinePos; if (consumedSpaces < paramHelpStringMargin) { - const ch = sourceFile.text.charCodeAt(pos); + let ch = sourceFile.text.charCodeAt(pos); if (ch === CharacterCodes.asterisk) { // Consume more spaces after asterisk pos = consumeWhiteSpacesOnTheLine(pos + 1, end, sourceFile, paramHelpStringMargin - consumedSpaces - 1); @@ -813,7 +815,7 @@ namespace ts { private namedDeclarations: Map; constructor(kind: SyntaxKind, pos: number, end: number) { - super(kind, pos, end); + super(kind, pos, end) } public update(newText: string, textChangeRange: TextChangeRange): SourceFile { @@ -841,16 +843,16 @@ namespace ts { } private computeNamedDeclarations(): Map { - const result: Map = {}; + let result: Map = {}; forEachChild(this, visit); return result; function addDeclaration(declaration: Declaration) { - const name = getDeclarationName(declaration); + let name = getDeclarationName(declaration); if (name) { - const declarations = getDeclarations(name); + let declarations = getDeclarations(name); declarations.push(declaration); } } @@ -861,13 +863,13 @@ namespace ts { function getDeclarationName(declaration: Declaration) { if (declaration.name) { - const result = getTextOfIdentifierOrLiteral(declaration.name); + let result = getTextOfIdentifierOrLiteral(declaration.name); if (result !== undefined) { return result; } if (declaration.name.kind === SyntaxKind.ComputedPropertyName) { - const expr = (declaration.name).expression; + let expr = (declaration.name).expression; if (expr.kind === SyntaxKind.PropertyAccessExpression) { return (expr).name.text; } @@ -897,12 +899,12 @@ namespace ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: - const functionDeclaration = node; - const declarationName = getDeclarationName(functionDeclaration); + let functionDeclaration = node; + let declarationName = getDeclarationName(functionDeclaration); if (declarationName) { - const declarations = getDeclarations(declarationName); - const lastDeclaration = lastOrUndefined(declarations); + let declarations = getDeclarations(declarationName); + let lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { @@ -978,7 +980,7 @@ namespace ts { break; case SyntaxKind.ImportDeclaration: - const importClause = (node).importClause; + let importClause = (node).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -1111,8 +1113,8 @@ namespace ts { } export interface Classifications { - spans: number[]; - endOfLineState: EndOfLineState; + spans: number[], + endOfLineState: EndOfLineState } export interface ClassifiedSpan { @@ -1169,7 +1171,7 @@ namespace ts { highlightSpans: HighlightSpan[]; } - export namespace HighlightSpanKind { + export module HighlightSpanKind { export const none = "none"; export const definition = "definition"; export const reference = "reference"; @@ -1218,7 +1220,7 @@ namespace ts { InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; - [s: string]: boolean | number | string; + [s: string]: boolean | number| string; } export interface DefinitionInfo { @@ -1498,7 +1500,7 @@ namespace ts { } // TODO: move these to enums - export namespace ScriptElementKind { + export module ScriptElementKind { export const unknown = ""; export const warning = "warning"; @@ -1527,7 +1529,7 @@ namespace ts { export const enumElement = "enum"; // Inside module and script only - // const v = .. + // let v = .. export const variableElement = "var"; // Inside function @@ -1579,7 +1581,7 @@ namespace ts { export const letElement = "let"; } - export namespace ScriptElementKindModifier { + export module ScriptElementKindModifier { export const none = ""; export const publicMemberModifier = "public"; export const privateMemberModifier = "private"; @@ -1721,8 +1723,8 @@ namespace ts { this.fileNameToEntry = createFileMap(); // Initialize the list with the root file names - const rootFileNames = host.getScriptFileNames(); - for (const fileName of rootFileNames) { + let rootFileNames = host.getScriptFileNames(); + for (let fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } @@ -1736,7 +1738,7 @@ namespace ts { private createEntry(fileName: string, path: Path) { let entry: HostFileInformation; - const scriptSnapshot = this.host.getScriptSnapshot(fileName); + let scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, @@ -1758,7 +1760,7 @@ namespace ts { } public getOrCreateEntry(fileName: string): HostFileInformation { - const path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName); + let path = toPath(fileName, this.currentDirectory, this.getCanonicalFileName) if (this.contains(path)) { return this.getEntry(path); } @@ -1767,7 +1769,7 @@ namespace ts { } public getRootFileNames(): string[] { - const fileNames: string[] = []; + let fileNames: string[] = []; this.fileNameToEntry.forEachValue((path, value) => { if (value) { @@ -1779,12 +1781,12 @@ namespace ts { } public getVersion(path: Path): string { - const file = this.getEntry(path); + let file = this.getEntry(path); return file && file.version; } public getScriptSnapshot(path: Path): IScriptSnapshot { - const file = this.getEntry(path); + let file = this.getEntry(path); return file && file.scriptSnapshot; } } @@ -1801,22 +1803,22 @@ namespace ts { } public getCurrentSourceFile(fileName: string): SourceFile { - const scriptSnapshot = this.host.getScriptSnapshot(fileName); + let scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - const version = this.host.getScriptVersion(fileName); + let version = this.host.getScriptVersion(fileName); let sourceFile: SourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it - sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents*/ true); + sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, ScriptTarget.Latest, version, /*setNodeParents:*/ true); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. - const editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); + let editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } @@ -1861,7 +1863,7 @@ namespace ts { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); + let options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions(); options.isolatedModules = true; @@ -1877,22 +1879,21 @@ namespace ts { options.noResolve = true; // if jsx is specified then treat file as .tsx - const inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); - const sourceFile = createSourceFile(inputFileName, input, options.target); + let inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts"); + let sourceFile = createSourceFile(inputFileName, input, options.target); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } sourceFile.renamedDependencies = transpileOptions.renamedDependencies; - const newLine = getNewLineCharacter(options); + let newLine = getNewLineCharacter(options); // Output let outputText: string; let sourceMapText: string; - // Create a compilerHost object to allow the compiler to read and write files - const compilerHost: CompilerHost = { + let compilerHost: CompilerHost = { getSourceFile: (fileName, target) => fileName === normalizeSlashes(inputFileName) ? sourceFile : undefined, writeFile: (name, text, writeByteOrderMark) => { if (fileExtensionIs(name, ".map")) { @@ -1913,7 +1914,7 @@ namespace ts { readFile: (fileName): string => "" }; - const program = createProgram([inputFileName], options, compilerHost); + let program = createProgram([inputFileName], options, compilerHost); let diagnostics: Diagnostic[]; if (transpileOptions.reportDiagnostics) { @@ -1933,15 +1934,15 @@ namespace ts { * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { - const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); + let output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing addRange(diagnostics, output.diagnostics); return output.outputText; } export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTarget: ScriptTarget, version: string, setNodeParents: boolean): SourceFile { - const text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); - const sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); + let text = scriptSnapshot.getText(0, scriptSnapshot.getLength()); + let sourceFile = createSourceFile(fileName, text, scriptTarget, setNodeParents); setSourceFileFields(sourceFile, scriptSnapshot, version); // after full parsing we can use table with interned strings as name table sourceFile.nameTable = sourceFile.identifiers; @@ -1960,12 +1961,12 @@ namespace ts { let newText: string; // grab the fragment from the beginning of the original text to the beginning of the span - const prefix = textChangeRange.span.start !== 0 + let prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text - const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + let suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; @@ -1975,7 +1976,7 @@ namespace ts { } else { // it was actual edit, fetch the fragment of new text that correspond to new span - const changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); + let changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix @@ -1984,7 +1985,7 @@ namespace ts { : (changedText + suffix); } - const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + let newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -2005,7 +2006,7 @@ namespace ts { } // Otherwise, just create a new source file. - return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true); + return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents:*/ true); } export function createGetCanonicalFileName(useCaseSensitivefileNames: boolean): (fileName: string) => string { @@ -2018,15 +2019,15 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - const buckets: Map> = {}; - const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); + let buckets: Map> = {}; + let getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyFromCompilationSettings(settings: CompilerOptions): string { return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + +"|" + settings.allowJs; } function getBucketForCompilationSettings(settings: CompilerOptions, createIfMissing: boolean): FileMap { - const key = getKeyFromCompilationSettings(settings); + let key = getKeyFromCompilationSettings(settings); let bucket = lookUp(buckets, key); if (!bucket && createIfMissing) { buckets[key] = bucket = createFileMap(); @@ -2035,9 +2036,9 @@ namespace ts { } function reportStats() { - const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => { - const entries = lookUp(buckets, name); - const sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; + let bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === '_').map(name => { + let entries = lookUp(buckets, name); + let sourceFiles: { name: string; refCount: number; references: string[]; }[] = []; entries.forEachValue((key, entry) => { sourceFiles.push({ name: key, @@ -2051,15 +2052,15 @@ namespace ts { sourceFiles }; }); - return JSON.stringify(bucketInfoArray, undefined, 2); + return JSON.stringify(bucketInfoArray, null, 2); } function acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ true); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ true); } function updateDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string): SourceFile { - return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring*/ false); + return acquireOrUpdateDocument(fileName, compilationSettings, scriptSnapshot, version, /*acquiring:*/ false); } function acquireOrUpdateDocument( @@ -2069,14 +2070,14 @@ namespace ts { version: string, acquiring: boolean): SourceFile { - const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); - const path = toPath(fileName, currentDirectory, getCanonicalFileName); + let bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true); + let path = toPath(fileName, currentDirectory, getCanonicalFileName); let entry = bucket.get(path); if (!entry) { Debug.assert(acquiring, "How could we be trying to update a document that the registry doesn't have?"); // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false); + let sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents:*/ false); entry = { sourceFile: sourceFile, @@ -2108,12 +2109,12 @@ namespace ts { } function releaseDocument(fileName: string, compilationSettings: CompilerOptions): void { - const bucket = getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/false); + let bucket = getBucketForCompilationSettings(compilationSettings, false); Debug.assert(bucket !== undefined); - const path = toPath(fileName, currentDirectory, getCanonicalFileName); + let path = toPath(fileName, currentDirectory, getCanonicalFileName); - const entry = bucket.get(path); + let entry = bucket.get(path); entry.languageServiceRefCount--; Debug.assert(entry.languageServiceRefCount >= 0); @@ -2131,19 +2132,19 @@ namespace ts { } export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { - const referencedFiles: FileReference[] = []; - const importedFiles: FileReference[] = []; + let referencedFiles: FileReference[] = []; + let importedFiles: FileReference[] = []; let ambientExternalModules: string[]; let isNoDefaultLib = false; function processTripleSlashDirectives(): void { - const commentRanges = getLeadingCommentRanges(sourceText, 0); + let commentRanges = getLeadingCommentRanges(sourceText, 0); forEach(commentRanges, commentRange => { - const comment = sourceText.substring(commentRange.pos, commentRange.end); - const referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); + let comment = sourceText.substring(commentRange.pos, commentRange.end); + let referencePathMatchResult = getFileReferenceFromReferencePath(comment, commentRange); if (referencePathMatchResult) { isNoDefaultLib = referencePathMatchResult.isNoDefaultLib; - const fileReference = referencePathMatchResult.fileReference; + let fileReference = referencePathMatchResult.fileReference; if (fileReference) { referencedFiles.push(fileReference); } @@ -2159,8 +2160,8 @@ namespace ts { } function recordModuleName() { - const importPath = scanner.getTokenValue(); - const pos = scanner.getTokenPos(); + let importPath = scanner.getTokenValue(); + let pos = scanner.getTokenPos(); importedFiles.push({ fileName: importPath, pos: pos, @@ -2212,7 +2213,7 @@ namespace ts { } } else if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { return true; } } @@ -2310,7 +2311,7 @@ namespace ts { if (token === SyntaxKind.Identifier || isKeyword(token)) { token = scanner.scan(); if (token === SyntaxKind.EqualsToken) { - if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { + if (tryConsumeRequireCall(/* skipCurrentToken */ true)) { return true; } } @@ -2409,7 +2410,7 @@ namespace ts { if (tryConsumeDeclare() || tryConsumeImport() || tryConsumeExport() || - (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) { + (detectJavaScriptImports && (tryConsumeRequireCall(/* skipCurrentToken */ false) || tryConsumeDefine()))) { continue; } else { @@ -2549,8 +2550,8 @@ namespace ts { return true; } else if (position === comment.end) { - const text = sourceFile.text; - const width = comment.end - comment.pos; + let text = sourceFile.text; + let width = comment.end - comment.pos; // is single line comment or just /* if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) { return true; @@ -2582,7 +2583,7 @@ namespace ts { } // A cache of completion entries for keywords, these do not change between sessions - const keywordCompletions: CompletionEntry[] = []; + let keywordCompletions: CompletionEntry[] = []; for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { keywordCompletions.push({ name: tokenToString(i), @@ -2672,15 +2673,15 @@ namespace ts { export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory())): LanguageService { - const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); + let syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); let ruleProvider: formatting.RulesProvider; let program: Program; let lastProjectVersion: string; - const useCaseSensitivefileNames = false; - const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); + let useCaseSensitivefileNames = false; + let cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken()); - const currentDirectory = host.getCurrentDirectory(); + let currentDirectory = host.getCurrentDirectory(); // Check if the localized messages json is set, otherwise query the host for it if (!localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) { localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages(); @@ -2692,10 +2693,10 @@ namespace ts { } } - const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); + let getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames); function getValidSourceFile(fileName: string): SourceFile { - const sourceFile = program.getSourceFile(fileName); + let sourceFile = program.getSourceFile(fileName); if (!sourceFile) { throw new Error("Could not find file: '" + fileName + "'."); } @@ -2715,7 +2716,7 @@ namespace ts { function synchronizeHostData(): void { // perform fast check if host supports it if (host.getProjectVersion) { - const hostProjectVersion = host.getProjectVersion(); + let hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion) { return; @@ -2739,17 +2740,17 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - const oldSettings = program && program.getCompilerOptions(); - const newSettings = hostCache.compilationSettings(); - const changesInCompilationSettingsAffectSyntax = oldSettings && + let oldSettings = program && program.getCompilerOptions(); + let newSettings = hostCache.compilationSettings(); + let changesInCompilationSettingsAffectSyntax = oldSettings && (oldSettings.target !== newSettings.target || oldSettings.module !== newSettings.module || oldSettings.noResolve !== newSettings.noResolve || - oldSettings.jsx !== newSettings.jsx || + oldSettings.jsx !== newSettings.jsx || oldSettings.allowJs !== newSettings.allowJs); // Now create a new compiler - const compilerHost: CompilerHost = { + let compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, getCancellationToken: () => cancellationToken, getCanonicalFileName, @@ -2765,22 +2766,22 @@ namespace ts { }, readFile: (fileName): string => { // stub missing host functionality - const entry = hostCache.getOrCreateEntry(fileName); + let entry = hostCache.getOrCreateEntry(fileName); return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength()); } }; if (host.resolveModuleNames) { - compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); + compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile) } - const newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); + let newProgram = createProgram(hostCache.getRootFileNames(), newSettings, compilerHost, program); // Release any files we have acquired in the old program but are // not part of the new program. if (program) { - const oldSourceFiles = program.getSourceFiles(); - for (const oldSourceFile of oldSourceFiles) { + let oldSourceFiles = program.getSourceFiles(); + for (let oldSourceFile of oldSourceFiles) { if (!newProgram.getSourceFile(oldSourceFile.fileName) || changesInCompilationSettingsAffectSyntax) { documentRegistry.releaseDocument(oldSourceFile.fileName, oldSettings); } @@ -2803,7 +2804,7 @@ namespace ts { // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. - const hostFileInformation = hostCache.getOrCreateEntry(fileName); + let hostFileInformation = hostCache.getOrCreateEntry(fileName); if (!hostFileInformation) { return undefined; } @@ -2813,7 +2814,7 @@ namespace ts { // can not be reused. we have to dump all syntax trees and create new ones. if (!changesInCompilationSettingsAffectSyntax) { // Check if the old program had this file already - const oldSourceFile = program && program.getSourceFile(fileName); + let oldSourceFile = program && program.getSourceFile(fileName); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to @@ -2850,7 +2851,7 @@ namespace ts { if (!sourceFile) { return false; } - const path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); + let path = sourceFile.path || toPath(sourceFile.fileName, currentDirectory, getCanonicalFileName); return sourceFile.version === hostCache.getVersion(path); } @@ -2861,13 +2862,13 @@ namespace ts { } // If number of files in the program do not match, it is not up-to-date - const rootFileNames = hostCache.getRootFileNames(); + let rootFileNames = hostCache.getRootFileNames(); if (program.getSourceFiles().length !== rootFileNames.length) { return false; } // If any file is not up-to-date, then the whole program is not up-to-date - for (const fileName of rootFileNames) { + for (let fileName of rootFileNames) { if (!sourceFileUpToDate(program.getSourceFile(fileName))) { return false; } @@ -2909,18 +2910,18 @@ namespace ts { function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); - const targetSourceFile = getValidSourceFile(fileName); + let targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. - const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); + let semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!program.getCompilerOptions().declaration) { return semanticDiagnostics; } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface - const declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); + let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return concatenate(semanticDiagnostics, declarationDiagnostics); } @@ -2936,14 +2937,14 @@ namespace ts { * @return undefined if the name is of external module otherwise a name with striped of any quote */ function getCompletionEntryDisplayNameForSymbol(symbol: Symbol, target: ScriptTarget, performCharacterChecks: boolean, location: Node): string { - const displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); + let displayName: string = getDeclaredName(program.getTypeChecker(), symbol, location); if (displayName) { - const firstCharCode = displayName.charCodeAt(0); + let firstCharCode = displayName.charCodeAt(0); // First check of the displayName is not external module; if it is an external module, it is not valid entry if ((symbol.flags & SymbolFlags.Namespace) && (firstCharCode === CharacterCodes.singleQuote || firstCharCode === CharacterCodes.doubleQuote)) { // If the symbol is external module, don't show it in the completion list - // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) + // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there) return undefined; } } @@ -2986,20 +2987,20 @@ namespace ts { } function getCompletionData(fileName: string, position: number) { - const typeChecker = program.getTypeChecker(); - const syntacticStart = new Date().getTime(); - const sourceFile = getValidSourceFile(fileName); - const isJavaScriptFile = isSourceFileJavaScript(sourceFile); + let typeChecker = program.getTypeChecker(); + let syntacticStart = new Date().getTime(); + let sourceFile = getValidSourceFile(fileName); + let isJavaScriptFile = isSourceFileJavaScript(sourceFile); let isJsDocTagName = false; let start = new Date().getTime(); - const currentToken = getTokenAtPosition(sourceFile, position); + let currentToken = getTokenAtPosition(sourceFile, position); log("getCompletionData: Get current token: " + (new Date().getTime() - start)); start = new Date().getTime(); // Completion not allowed inside comments, bail out if this is the case - const insideComment = isInsideComment(sourceFile, currentToken, position); + let insideComment = isInsideComment(sourceFile, currentToken, position); log("getCompletionData: Is inside comment: " + (new Date().getTime() - start)); if (insideComment) { @@ -3013,7 +3014,7 @@ namespace ts { // /** @type {number | string} */ // Completion should work in the brackets let insideJsDocTagExpression = false; - const tag = getJsDocTagAtPosition(sourceFile, position); + let tag = getJsDocTagAtPosition(sourceFile, position); if (tag) { if (tag.tagName.pos <= position && position <= tag.tagName.end) { isJsDocTagName = true; @@ -3023,7 +3024,7 @@ namespace ts { case SyntaxKind.JSDocTypeTag: case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocReturnTag: - const tagWithExpression = tag; + let tagWithExpression = tag; if (tagWithExpression.typeExpression) { insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end; } @@ -3044,7 +3045,7 @@ namespace ts { } start = new Date().getTime(); - const previousToken = findPrecedingToken(position, sourceFile); + let previousToken = findPrecedingToken(position, sourceFile); log("getCompletionData: Get previous token 1: " + (new Date().getTime() - start)); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. @@ -3054,7 +3055,7 @@ namespace ts { // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS| // Skip this partial identifier and adjust the contextToken to the token that precedes it. if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) { - const start = new Date().getTime(); + let start = new Date().getTime(); contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile); log("getCompletionData: Get previous token 2: " + (new Date().getTime() - start)); } @@ -3075,7 +3076,7 @@ namespace ts { return undefined; } - const { parent, kind } = contextToken; + let { parent, kind } = contextToken; if (kind === SyntaxKind.DotToken) { if (parent.kind === SyntaxKind.PropertyAccessExpression) { node = (contextToken.parent).expression; @@ -3102,7 +3103,7 @@ namespace ts { } } - const semanticStart = new Date().getTime(); + let semanticStart = new Date().getTime(); let isMemberCompletion: boolean; let isNewIdentifierLocation: boolean; let symbols: Symbol[] = []; @@ -3111,7 +3112,7 @@ namespace ts { getTypeScriptMemberSymbols(); } else if (isRightOfOpenTag) { - const tagSymbols = typeChecker.getJsxIntrinsicTagNames(); + let tagSymbols = typeChecker.getJsxIntrinsicTagNames(); if (tryGetGlobalSymbols()) { symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value))); } @@ -3122,7 +3123,7 @@ namespace ts { isNewIdentifierLocation = false; } else if (isStartingCloseTag) { - const tagName = (contextToken.parent.parent).openingElement.tagName; + let tagName = (contextToken.parent.parent).openingElement.tagName; symbols = [typeChecker.getSymbolAtLocation(tagName)]; isMemberCompletion = true; @@ -3156,7 +3157,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.HasExports) { // Extract module or enum members - const exportedSymbols = typeChecker.getExportsOfModule(symbol); + let exportedSymbols = typeChecker.getExportsOfModule(symbol); forEach(exportedSymbols, symbol => { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); @@ -3165,14 +3166,14 @@ namespace ts { } } - const type = typeChecker.getTypeAtLocation(node); + let type = typeChecker.getTypeAtLocation(node); addTypeProperties(type); } function addTypeProperties(type: Type) { if (type) { // Filter private properties - for (const symbol of type.getApparentProperties()) { + for (let symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccess((node.parent), symbol.name)) { symbols.push(symbol); } @@ -3184,8 +3185,8 @@ namespace ts { // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - const unionType = type; - for (const elementType of unionType.types) { + let unionType = type; + for (let elementType of unionType.types) { addTypeProperties(elementType); } } @@ -3255,14 +3256,14 @@ namespace ts { // - 'contextToken' was adjusted to the token prior to 'previousToken' // because we were at the end of an identifier. // - 'previousToken' is defined. - const adjustedPosition = previousToken !== contextToken ? + let adjustedPosition = previousToken !== contextToken ? previousToken.getStart() : position; - const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; + let scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; /// TODO filter meaning based on the current context - const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; + let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings); return true; @@ -3281,8 +3282,8 @@ namespace ts { } function isCompletionListBlocker(contextToken: Node): boolean { - const start = new Date().getTime(); - const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || + let start = new Date().getTime(); + let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken); @@ -3309,27 +3310,27 @@ namespace ts { function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { - const containingNodeKind = previousToken.parent.kind; + let containingNodeKind = previousToken.parent.kind; switch (previousToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.CallExpression // func( a, | || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ || containingNodeKind === SyntaxKind.NewExpression // new C(a, | || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | + || containingNodeKind === SyntaxKind.BinaryExpression // let x = (a, | || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list| case SyntaxKind.OpenParenToken: return containingNodeKind === SyntaxKind.CallExpression // func( | || containingNodeKind === SyntaxKind.Constructor // constructor( | || containingNodeKind === SyntaxKind.NewExpression // new C(a| - || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // let x = (a| || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ case SyntaxKind.OpenBracketToken: return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ + || containingNodeKind === SyntaxKind.ComputedPropertyName // [ | /* this can become an index signature */ case SyntaxKind.ModuleKeyword: // module | case SyntaxKind.NamespaceKeyword: // namespace | @@ -3342,7 +3343,7 @@ namespace ts { return containingNodeKind === SyntaxKind.ClassDeclaration; // class A{ | case SyntaxKind.EqualsToken: - return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| + return containingNodeKind === SyntaxKind.VariableDeclaration // let x = a| || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| case SyntaxKind.TemplateHead: @@ -3374,8 +3375,8 @@ namespace ts { || contextToken.kind === SyntaxKind.StringLiteralType || contextToken.kind === SyntaxKind.RegularExpressionLiteral || isTemplateLiteralKind(contextToken.kind)) { - const start = contextToken.getStart(); - const end = contextToken.getEnd(); + let start = contextToken.getStart(); + let end = contextToken.getEnd(); // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. @@ -3419,7 +3420,7 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); if (isVariableLike(rootDeclaration)) { // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired @@ -3430,7 +3431,7 @@ namespace ts { } } else { - Debug.fail("Root declaration is not variable-like."); + Debug.fail("Root declaration is not variable-like.") } } else { @@ -3441,7 +3442,7 @@ namespace ts { return false; } - const typeMembers = typeChecker.getPropertiesOfType(typeForObject); + let typeMembers = typeChecker.getPropertiesOfType(typeForObject); if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list symbols = filterObjectMembersList(typeMembers, existingMembers); @@ -3465,11 +3466,11 @@ namespace ts { * @returns true if 'symbols' was successfully populated; false otherwise. */ function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { - const declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? SyntaxKind.ImportDeclaration : SyntaxKind.ExportDeclaration; - const importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); - const moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; if (!moduleSpecifier) { return false; @@ -3479,7 +3480,7 @@ namespace ts { isNewIdentifierLocation = false; let exports: Symbol[]; - const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); if (moduleSpecifierSymbol) { exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } @@ -3496,9 +3497,9 @@ namespace ts { function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern { if (contextToken) { switch (contextToken.kind) { - case SyntaxKind.OpenBraceToken: // const x = { | - case SyntaxKind.CommaToken: // const x = { a: 0, | - const parent = contextToken.parent; + case SyntaxKind.OpenBraceToken: // let x = { | + case SyntaxKind.CommaToken: // let x = { a: 0, | + let parent = contextToken.parent; if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) { return parent; } @@ -3531,8 +3532,8 @@ namespace ts { function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { - const parent = contextToken.parent; - switch (contextToken.kind) { + let parent = contextToken.parent; + switch(contextToken.kind) { case SyntaxKind.LessThanSlashToken: case SyntaxKind.SlashToken: case SyntaxKind.Identifier: @@ -3595,7 +3596,7 @@ namespace ts { * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { - const containingNodeKind = contextToken.parent.kind; + let containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: return containingNodeKind === SyntaxKind.VariableDeclaration || @@ -3625,13 +3626,13 @@ namespace ts { case SyntaxKind.OpenBraceToken: return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { | containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface a { | - containingNodeKind === SyntaxKind.TypeLiteral; // const x : { | + containingNodeKind === SyntaxKind.TypeLiteral; // let x : { | case SyntaxKind.SemicolonToken: return containingNodeKind === SyntaxKind.PropertySignature && contextToken.parent && contextToken.parent.parent && (contextToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration || // interface a { f; | - contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // const x : { a; | + contextToken.parent.parent.kind === SyntaxKind.TypeLiteral); // let x : { a; | case SyntaxKind.LessThanToken: return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | @@ -3698,7 +3699,7 @@ namespace ts { function isDotOfNumericLiteral(contextToken: Node): boolean { if (contextToken.kind === SyntaxKind.NumericLiteral) { - const text = contextToken.getFullText(); + let text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3715,15 +3716,15 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - const exisingImportsOrExports: Map = {}; + let exisingImportsOrExports: Map = {}; - for (const element of namedImportsOrExports) { + for (let element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out if (element.getStart() <= position && position <= element.getEnd()) { continue; } - const name = element.propertyName || element.name; + let name = element.propertyName || element.name; exisingImportsOrExports[name.text] = true; } @@ -3745,8 +3746,8 @@ namespace ts { return contextualMemberSymbols; } - const existingMemberNames: Map = {}; - for (const m of existingMembers) { + let existingMemberNames: Map = {}; + for (let m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && m.kind !== SyntaxKind.ShorthandPropertyAssignment && @@ -3765,7 +3766,7 @@ namespace ts { if (m.kind === SyntaxKind.BindingElement && (m).propertyName) { // include only identifiers in completion list if ((m).propertyName.kind === SyntaxKind.Identifier) { - existingName = ((m).propertyName).text; + existingName = ((m).propertyName).text } } else { @@ -3788,8 +3789,8 @@ namespace ts { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - const seenNames: Map = {}; - for (const attr of attributes) { + let seenNames: Map = {}; + for (let attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { continue; @@ -3808,21 +3809,21 @@ namespace ts { function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo { synchronizeHostData(); - const completionData = getCompletionData(fileName, position); + let completionData = getCompletionData(fileName, position); if (!completionData) { return undefined; } - const { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; + let { symbols, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot, isJsDocTagName } = completionData; if (isJsDocTagName) { // If the current position is a jsDoc tag name, only tag names should be provided for completion return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() }; } - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); - const entries: CompletionEntry[] = []; + let entries: CompletionEntry[] = []; if (isRightOfDot && isSourceFileJavaScript(sourceFile)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries); @@ -3844,16 +3845,16 @@ namespace ts { return { isMemberCompletion, isNewIdentifierLocation, entries }; function getJavaScriptCompletionEntries(sourceFile: SourceFile, uniqueNames: Map): CompletionEntry[] { - const entries: CompletionEntry[] = []; - const target = program.getCompilerOptions().target; + let entries: CompletionEntry[] = []; + let target = program.getCompilerOptions().target; - const nameTable = getNameTable(sourceFile); - for (const name in nameTable) { + let nameTable = getNameTable(sourceFile); + for (let name in nameTable) { if (!uniqueNames[name]) { uniqueNames[name] = name; - const displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks*/ true); + let displayName = getCompletionEntryDisplayName(name, target, /*performCharacterChecks:*/ true); if (displayName) { - const entry = { + let entry = { name: displayName, kind: ScriptElementKind.warning, kindModifiers: "", @@ -3874,7 +3875,7 @@ namespace ts { kind: ScriptElementKind.keyword, kindModifiers: "", sortText: "0", - }; + } })); } @@ -3882,7 +3883,7 @@ namespace ts { // Try to get a valid display name for this symbol, if we could not find one, then ignore it. // We would like to only show things that can be added after a dot, so for instance numeric properties can // not be accessed with a dot (a.1 <- invalid) - const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location); + let displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks:*/ true, location); if (!displayName) { return undefined; } @@ -3904,13 +3905,13 @@ namespace ts { } function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map { - const start = new Date().getTime(); - const uniqueNames: Map = {}; + let start = new Date().getTime(); + let uniqueNames: Map = {}; if (symbols) { - for (const symbol of symbols) { - const entry = createCompletionEntry(symbol, location); + for (let symbol of symbols) { + let entry = createCompletionEntry(symbol, location); if (entry) { - const id = escapeIdentifier(entry.name); + let id = escapeIdentifier(entry.name); if (!lookUp(uniqueNames, id)) { entries.push(entry); uniqueNames[id] = id; @@ -3928,19 +3929,19 @@ namespace ts { synchronizeHostData(); // Compute all the completion symbols again. - const completionData = getCompletionData(fileName, position); + let completionData = getCompletionData(fileName, position); if (completionData) { - const { symbols, location } = completionData; + let { symbols, location } = completionData; // Find the symbol with the matching entry name. - const target = program.getCompilerOptions().target; + let target = program.getCompilerOptions().target; // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - const symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks*/ false, location) === entryName ? s : undefined); + let symbol = forEach(symbols, s => getCompletionEntryDisplayNameForSymbol(s, target, /*performCharacterChecks:*/ false, location) === entryName ? s : undefined); if (symbol) { - const { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); + let { displayParts, documentation, symbolKind } = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getValidSourceFile(fileName), location, location, SemanticMeaning.All); return { name: entryName, kindModifiers: getSymbolModifiers(symbol), @@ -3952,7 +3953,7 @@ namespace ts { } // Didn't find a symbol with this name. See if we can find a keyword instead. - const keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); + let keywordCompletion = forEach(keywordCompletions, c => c.name === entryName); if (keywordCompletion) { return { name: entryName, @@ -3968,7 +3969,7 @@ namespace ts { // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(symbol: Symbol, location: Node): string { - const flags = symbol.getFlags(); + let flags = symbol.getFlags(); if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? ScriptElementKind.localClassElement : ScriptElementKind.classElement; @@ -3977,7 +3978,7 @@ namespace ts { if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; - const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); + let result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, location); if (result === ScriptElementKind.unknown) { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; @@ -3989,7 +3990,7 @@ namespace ts { } function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, location: Node) { - const typeChecker = program.getTypeChecker(); + let typeChecker = program.getTypeChecker(); if (typeChecker.isUndefinedSymbol(symbol)) { return ScriptElementKind.variableElement; @@ -4018,8 +4019,8 @@ namespace ts { if (flags & SymbolFlags.Property) { if (flags & SymbolFlags.SyntheticProperty) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { - const rootSymbolFlags = rootSymbol.getFlags(); + let unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + let rootSymbolFlags = rootSymbol.getFlags(); if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { return ScriptElementKind.memberVariableElement; } @@ -4027,8 +4028,8 @@ namespace ts { }); if (!unionPropertyKind) { // If this was union of all methods, - // make sure it has call signatures before we can label it as method - const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); + //make sure it has call signatures before we can label it as method + let typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { return ScriptElementKind.memberFunctionElement; } @@ -4052,11 +4053,11 @@ namespace ts { function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, location: Node, semanticMeaning = getMeaningFromLocation(location)) { - const typeChecker = program.getTypeChecker(); + let typeChecker = program.getTypeChecker(); - const displayParts: SymbolDisplayPart[] = []; + let displayParts: SymbolDisplayPart[] = []; let documentation: SymbolDisplayPart[]; - const symbolFlags = symbol.flags; + let symbolFlags = symbol.flags; let symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, location); let hasAddedSymbolInfo: boolean; let type: Type; @@ -4072,7 +4073,7 @@ namespace ts { type = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (type) { if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { - const right = (location.parent).name; + let right = (location.parent).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -4089,15 +4090,15 @@ namespace ts { } if (callExpression) { - const candidateSignatures: Signature[] = []; + let candidateSignatures: Signature[] = []; signature = typeChecker.getResolvedSignature(callExpression, candidateSignatures); if (!signature && candidateSignatures.length) { // Use the first candidate: signature = candidateSignatures[0]; } - const useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; - const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); + let useConstructSignatures = callExpression.kind === SyntaxKind.NewExpression || callExpression.expression.kind === SyntaxKind.SuperKeyword; + let allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (!contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain @@ -4155,8 +4156,8 @@ namespace ts { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - const functionDeclaration = location.parent; - const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); + let functionDeclaration = location.parent; + let allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); } @@ -4225,8 +4226,8 @@ namespace ts { } if (symbolFlags & SymbolFlags.Module) { addNewLineIfDisplayPartsExist(); - const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); - const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + let declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + let isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); displayParts.push(spacePart()); addFullSymbolName(symbol); @@ -4278,9 +4279,9 @@ namespace ts { } if (symbolFlags & SymbolFlags.EnumMember) { addPrefixForAnyFunctionOrVar(symbol, "enum member"); - const declaration = symbol.declarations[0]; + let declaration = symbol.declarations[0]; if (declaration.kind === SyntaxKind.EnumMember) { - const constantValue = typeChecker.getConstantValue(declaration); + let constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4296,7 +4297,7 @@ namespace ts { addFullSymbolName(symbol); ts.forEach(symbol.declarations, declaration => { if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { - const importEqualsDeclaration = declaration; + let importEqualsDeclaration = declaration; if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4307,7 +4308,7 @@ namespace ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); + let internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -4331,7 +4332,7 @@ namespace ts { displayParts.push(spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) { - const typeParameterParts = mapToDisplayParts(writer => { + let typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(type, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4346,7 +4347,7 @@ namespace ts { symbolFlags & SymbolFlags.Signature || symbolFlags & SymbolFlags.Accessor || symbolKind === ScriptElementKind.memberFunctionElement) { - const allSignatures = type.getCallSignatures(); + let allSignatures = type.getCallSignatures(); addSignatureDisplayParts(allSignatures[0], allSignatures); } } @@ -4369,7 +4370,7 @@ namespace ts { } function addFullSymbolName(symbol: Symbol, enclosingDeclaration?: Node) { - const fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + let fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration || sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing); addRange(displayParts, fullSymbolDisplayParts); } @@ -4415,7 +4416,7 @@ namespace ts { } function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node) { - const typeParameterParts = mapToDisplayParts(writer => { + let typeParameterParts = mapToDisplayParts(writer => { typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplayFromSymbol(symbol, writer, enclosingDeclaration); }); addRange(displayParts, typeParameterParts); @@ -4425,8 +4426,8 @@ namespace ts { function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); + let sourceFile = getValidSourceFile(fileName); + let node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } @@ -4435,8 +4436,8 @@ namespace ts { return undefined; } - const typeChecker = program.getTypeChecker(); - const symbol = typeChecker.getSymbolAtLocation(node); + let typeChecker = program.getTypeChecker(); + let symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { // Try getting just type at this position and show @@ -4448,7 +4449,7 @@ namespace ts { case SyntaxKind.ThisType: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - const type = typeChecker.getTypeAtLocation(node); + let type = typeChecker.getTypeAtLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -4463,7 +4464,7 @@ namespace ts { return undefined; } - const displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); + let displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), node); return { kind: displayPartsDocumentationsAndKind.symbolKind, kindModifiers: getSymbolModifiers(symbol), @@ -4485,13 +4486,13 @@ namespace ts { } function getDefinitionFromSymbol(symbol: Symbol, node: Node): DefinitionInfo[] { - const typeChecker = program.getTypeChecker(); - const result: DefinitionInfo[] = []; - const declarations = symbol.getDeclarations(); - const symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - const symbolKind = getSymbolKind(symbol, node); - const containerSymbol = symbol.parent; - const containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; + let typeChecker = program.getTypeChecker(); + let result: DefinitionInfo[] = []; + let declarations = symbol.getDeclarations(); + let symbolName = typeChecker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol + let symbolKind = getSymbolKind(symbol, node); + let containerSymbol = symbol.parent; + let containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : ""; if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) && !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { @@ -4509,7 +4510,7 @@ namespace ts { if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { // Find the first class-like declaration and try to get the construct signature. - for (const declaration of symbol.getDeclarations()) { + for (let declaration of symbol.getDeclarations()) { if (isClassLike(declaration)) { return tryAddSignature(declaration.members, /*selectConstructors*/ true, @@ -4534,7 +4535,7 @@ namespace ts { } function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - const declarations: Declaration[] = []; + let declarations: Declaration[] = []; let definition: Declaration; forEach(signatureDeclarations, d => { @@ -4562,24 +4563,24 @@ namespace ts { function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); + let node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } // Labels if (isJumpStatementTarget(node)) { - const labelName = (node).text; - const label = getTargetLabel((node.parent), (node).text); + let labelName = (node).text; + let label = getTargetLabel((node.parent), (node).text); return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments - const comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); + let comment = forEach(sourceFile.referencedFiles, r => (r.pos <= position && position < r.end) ? r : undefined); if (comment) { - const referenceFile = tryResolveScriptReference(program, sourceFile, comment); + let referenceFile = tryResolveScriptReference(program, sourceFile, comment); if (referenceFile) { return [{ fileName: referenceFile.fileName, @@ -4593,7 +4594,7 @@ namespace ts { return undefined; } - const typeChecker = program.getTypeChecker(); + let typeChecker = program.getTypeChecker(); let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. node is string or number keyword, @@ -4607,7 +4608,7 @@ namespace ts { // import {A, B} from "mod"; // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { - const declaration = symbol.declarations[0]; + let declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { symbol = typeChecker.getAliasedSymbol(symbol); } @@ -4619,15 +4620,15 @@ namespace ts { // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + let shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); if (!shorthandSymbol) { return []; } - const shorthandDeclarations = shorthandSymbol.getDeclarations(); - const shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); - const shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); - const shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); + let shorthandDeclarations = shorthandSymbol.getDeclarations(); + let shorthandSymbolKind = getSymbolKind(shorthandSymbol, node); + let shorthandSymbolName = typeChecker.symbolToString(shorthandSymbol); + let shorthandContainerName = typeChecker.symbolToString(symbol.parent, node); return map(shorthandDeclarations, declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } @@ -4639,27 +4640,27 @@ namespace ts { function getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); + let node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } - const typeChecker = program.getTypeChecker(); + let typeChecker = program.getTypeChecker(); - const symbol = typeChecker.getSymbolAtLocation(node); + let symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { return undefined; } - const type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); + let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node); if (!type) { return undefined; } if (type.flags & TypeFlags.Union) { - const result: DefinitionInfo[] = []; + let result: DefinitionInfo[] = []; forEach((type).types, t => { if (t.symbol) { addRange(/*to*/ result, /*from*/ getDefinitionFromSymbol(t.symbol, node)); @@ -4679,7 +4680,7 @@ namespace ts { let results = getOccurrencesAtPositionCore(fileName, position); if (results) { - const sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); + let sourceFile = getCanonicalFileName(normalizeSlashes(fileName)); // Get occurrences only supports reporting occurrences for the file queried. So // filter down to that list. @@ -4693,10 +4694,10 @@ namespace ts { synchronizeHostData(); filesToSearch = map(filesToSearch, normalizeSlashes); - const sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); - const sourceFile = getValidSourceFile(fileName); + let sourceFilesToSearch = filter(program.getSourceFiles(), f => contains(filesToSearch, f.fileName)); + let sourceFile = getValidSourceFile(fileName); - const node = getTouchingWord(sourceFile, position); + let node = getTouchingWord(sourceFile, position); if (!node) { return undefined; } @@ -4704,8 +4705,8 @@ namespace ts { return getSemanticDocumentHighlights(node) || getSyntacticDocumentHighlights(node); function getHighlightSpanForNode(node: Node): HighlightSpan { - const start = node.getStart(); - const end = node.getEnd(); + let start = node.getStart(); + let end = node.getEnd(); return { fileName: sourceFile.fileName, @@ -4722,7 +4723,7 @@ namespace ts { isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - const referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false); + let referencedSymbols = getReferencedSymbolsForNode(node, sourceFilesToSearch, /*findInStrings:*/ false, /*findInComments:*/ false); return convertReferencedSymbols(referencedSymbols); } @@ -4733,11 +4734,11 @@ namespace ts { return undefined; } - const fileNameToDocumentHighlights: Map = {}; - const result: DocumentHighlights[] = []; - for (const referencedSymbol of referencedSymbols) { - for (const referenceEntry of referencedSymbol.references) { - const fileName = referenceEntry.fileName; + let fileNameToDocumentHighlights: Map = {}; + let result: DocumentHighlights[] = []; + for (let referencedSymbol of referencedSymbols) { + for (let referenceEntry of referencedSymbol.references) { + let fileName = referenceEntry.fileName; let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName); if (!documentHighlights) { documentHighlights = { fileName, highlightSpans: [] }; @@ -4758,9 +4759,9 @@ namespace ts { } function getSyntacticDocumentHighlights(node: Node): DocumentHighlights[] { - const fileName = sourceFile.fileName; + let fileName = sourceFile.fileName; - const highlightSpans = getHighlightSpans(node); + let highlightSpans = getHighlightSpans(node); if (!highlightSpans || highlightSpans.length === 0) { return undefined; } @@ -4864,7 +4865,7 @@ namespace ts { * into function boundaries and try-blocks with catch-clauses. */ function aggregateOwnedThrowStatements(node: Node): ThrowStatement[] { - const statementAccumulator: ThrowStatement[] = []; + let statementAccumulator: ThrowStatement[] = [] aggregate(node); return statementAccumulator; @@ -4873,7 +4874,7 @@ namespace ts { statementAccumulator.push(node); } else if (node.kind === SyntaxKind.TryStatement) { - const tryStatement = node; + let tryStatement = node; if (tryStatement.catchClause) { aggregate(tryStatement.catchClause); @@ -4904,7 +4905,7 @@ namespace ts { let child: Node = throwStatement; while (child.parent) { - const parent = child.parent; + let parent = child.parent; if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; @@ -4913,7 +4914,7 @@ namespace ts { // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. if (parent.kind === SyntaxKind.TryStatement) { - const tryStatement = parent; + let tryStatement = parent; if (tryStatement.tryBlock === child && tryStatement.catchClause) { return child; @@ -4927,7 +4928,7 @@ namespace ts { } function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] { - const statementAccumulator: BreakOrContinueStatement[] = []; + let statementAccumulator: BreakOrContinueStatement[] = [] aggregate(node); return statementAccumulator; @@ -4943,7 +4944,7 @@ namespace ts { } function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { - const actualOwner = getBreakOrContinueOwner(statement); + let actualOwner = getBreakOrContinueOwner(statement); return actualOwner && actualOwner === owner; } @@ -4978,7 +4979,7 @@ namespace ts { } function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): HighlightSpan[] { - const container = declaration.parent; + let container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { @@ -5008,8 +5009,8 @@ namespace ts { return undefined; } - const keywords: Node[] = []; - const modifierFlag: NodeFlags = getFlagFromModifier(modifier); + let keywords: Node[] = []; + let modifierFlag: NodeFlags = getFlagFromModifier(modifier); let nodes: Node[]; switch (container.kind) { @@ -5034,7 +5035,7 @@ namespace ts { // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - const constructor = forEach((container).members, member => { + let constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -5047,7 +5048,7 @@ namespace ts { } break; default: - Debug.fail("Invalid container kind."); + Debug.fail("Invalid container kind.") } forEach(nodes, node => { @@ -5090,7 +5091,7 @@ namespace ts { } function getGetAndSetOccurrences(accessorDeclaration: AccessorDeclaration): HighlightSpan[] { - const keywords: Node[] = []; + let keywords: Node[] = []; tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.GetAccessor); tryPushAccessorKeyword(accessorDeclaration.symbol, SyntaxKind.SetAccessor); @@ -5098,7 +5099,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); function tryPushAccessorKeyword(accessorSymbol: Symbol, accessorKind: SyntaxKind): void { - const accessor = getDeclarationOfKind(accessorSymbol, accessorKind); + let accessor = getDeclarationOfKind(accessorSymbol, accessorKind); if (accessor) { forEach(accessor.getChildren(), child => pushKeywordIf(keywords, child, SyntaxKind.GetKeyword, SyntaxKind.SetKeyword)); @@ -5107,9 +5108,9 @@ namespace ts { } function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): HighlightSpan[] { - const declarations = constructorDeclaration.symbol.getDeclarations(); + let declarations = constructorDeclaration.symbol.getDeclarations() - const keywords: Node[] = []; + let keywords: Node[] = []; forEach(declarations, declaration => { forEach(declaration.getChildren(), token => { @@ -5121,12 +5122,12 @@ namespace ts { } function getLoopBreakContinueOccurrences(loopNode: IterationStatement): HighlightSpan[] { - const keywords: Node[] = []; + let keywords: Node[] = []; if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === SyntaxKind.DoStatement) { - const loopTokens = loopNode.getChildren(); + let loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { @@ -5136,7 +5137,7 @@ namespace ts { } } - const breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); + let breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { @@ -5148,7 +5149,7 @@ namespace ts { } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { - const owner = getBreakOrContinueOwner(breakOrContinueStatement); + let owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { @@ -5157,7 +5158,7 @@ namespace ts { case SyntaxKind.ForOfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner); + return getLoopBreakContinueOccurrences(owner) case SyntaxKind.SwitchStatement: return getSwitchCaseDefaultOccurrences(owner); @@ -5168,7 +5169,7 @@ namespace ts { } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): HighlightSpan[] { - const keywords: Node[] = []; + let keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -5176,7 +5177,7 @@ namespace ts { forEach(switchStatement.caseBlock.clauses, clause => { pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - const breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); + let breaksAndContinues = aggregateAllBreakAndContinueStatements(clause); forEach(breaksAndContinues, statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { @@ -5189,7 +5190,7 @@ namespace ts { } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): HighlightSpan[] { - const keywords: Node[] = []; + let keywords: Node[] = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); @@ -5198,7 +5199,7 @@ namespace ts { } if (tryStatement.finallyBlock) { - const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); + let finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } @@ -5206,13 +5207,13 @@ namespace ts { } function getThrowOccurrences(throwStatement: ThrowStatement): HighlightSpan[] { - const owner = getThrowStatementOwner(throwStatement); + let owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - const keywords: Node[] = []; + let keywords: Node[] = []; forEach(aggregateOwnedThrowStatements(owner), throwStatement => { pushKeywordIf(keywords, throwStatement.getFirstToken(), SyntaxKind.ThrowKeyword); @@ -5230,14 +5231,14 @@ namespace ts { } function getReturnOccurrences(returnStatement: ReturnStatement): HighlightSpan[] { - const func = getContainingFunction(returnStatement); + let func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } - const keywords: Node[] = []; + let keywords: Node[] = [] forEachReturnStatement(func.body, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -5251,7 +5252,7 @@ namespace ts { } function getIfElseOccurrences(ifStatement: IfStatement): HighlightSpan[] { - const keywords: Node[] = []; + let keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (ifStatement.parent).elseStatement === ifStatement) { @@ -5260,7 +5261,7 @@ namespace ts { // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (ifStatement) { - const children = ifStatement.getChildren(); + let children = ifStatement.getChildren(); pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. @@ -5271,20 +5272,20 @@ namespace ts { } if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) { - break; + break } ifStatement = ifStatement.elseStatement; } - const result: HighlightSpan[] = []; + let result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { - const elseKeyword = keywords[i]; - const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. + let elseKeyword = keywords[i]; + let ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. let shouldCombindElseAndIf = true; @@ -5327,9 +5328,9 @@ namespace ts { return undefined; } - const result: ReferenceEntry[] = []; - for (const entry of documentHighlights) { - for (const highlightSpan of entry.highlightSpans) { + let result: ReferenceEntry[] = []; + for (let entry of documentHighlights) { + for (let highlightSpan of entry.highlightSpans) { result.push({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, @@ -5347,9 +5348,9 @@ namespace ts { return undefined; } - const referenceEntries: ReferenceEntry[] = []; + let referenceEntries: ReferenceEntry[] = []; - for (const referenceSymbol of referenceSymbols) { + for (let referenceSymbol of referenceSymbols) { addRange(referenceEntries, referenceSymbol.references); } @@ -5357,17 +5358,17 @@ namespace ts { } function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - const referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + let referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number): ReferencedSymbol[] { - const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false); + function findReferences(fileName: string, position: number): ReferencedSymbol[]{ + let referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); @@ -5376,17 +5377,17 @@ namespace ts { function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); - const node = getTouchingPropertyName(sourceFile, position); + let node = getTouchingPropertyName(sourceFile, position); if (!node) { return undefined; } if (node.kind !== SyntaxKind.Identifier && // TODO (drosen): This should be enabled in a later release - currently breaks rename. - // node.kind !== SyntaxKind.ThisKeyword && - // node.kind !== SyntaxKind.SuperKeyword && + //node.kind !== SyntaxKind.ThisKeyword && + //node.kind !== SyntaxKind.SuperKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -5397,12 +5398,12 @@ namespace ts { } function getReferencedSymbolsForNode(node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { - const typeChecker = program.getTypeChecker(); + let typeChecker = program.getTypeChecker(); // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { - const labelDefinition = getTargetLabel((node.parent), (node).text); + let labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; @@ -5421,7 +5422,7 @@ namespace ts { return getReferencesForSuperKeyword(node); } - const symbol = typeChecker.getSymbolAtLocation(node); + let symbol = typeChecker.getSymbolAtLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -5429,7 +5430,7 @@ namespace ts { return undefined; } - const declarations = symbol.declarations; + let declarations = symbol.declarations; // The symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!declarations || !declarations.length) { @@ -5439,29 +5440,29 @@ namespace ts { let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references - const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); + let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); // Get the text to search for. // Note: if this is an external module symbol, the name doesn't include quotes. - const declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + let declaredName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). - const scope = getSymbolScope(symbol); + let scope = getSymbolScope(symbol); // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. - const symbolToIndex: number[] = []; + let symbolToIndex: number[] = []; if (scope) { result = []; getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { - const internedName = getInternedName(symbol, node, declarations); - for (const sourceFile of sourceFiles) { + let internedName = getInternedName(symbol, node, declarations) + for (let sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - const nameTable = getNameTable(sourceFile); + let nameTable = getNameTable(sourceFile); if (lookUp(nameTable, internedName)) { result = result || []; @@ -5473,9 +5474,9 @@ namespace ts { return result; function getDefinition(symbol: Symbol): DefinitionInfo { - const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); - const name = map(info.displayParts, p => p.text).join(""); - const declarations = symbol.declarations; + let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node); + let name = map(info.displayParts, p => p.text).join(""); + let declarations = symbol.declarations; if (!declarations || declarations.length === 0) { return undefined; } @@ -5505,7 +5506,7 @@ namespace ts { // Try to get the local symbol if we're dealing with an 'export default' // since that symbol has the "true" name. - const localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); + let localExportDefaultSymbol = getLocalSymbolForExportDefault(symbol); symbol = localExportDefaultSymbol || symbol; return stripQuotes(symbol.name); @@ -5522,14 +5523,14 @@ namespace ts { function getSymbolScope(symbol: Symbol): Node { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. - const valueDeclaration = symbol.valueDeclaration; + let valueDeclaration = symbol.valueDeclaration; if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } // If this is private property or method, the scope is the containing class if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) { - const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); + let privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined); if (privateDeclaration) { return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } @@ -5547,12 +5548,12 @@ namespace ts { return undefined; } - let scope: Node; + let scope: Node = undefined; - const declarations = symbol.getDeclarations(); + let declarations = symbol.getDeclarations(); if (declarations) { - for (const declaration of declarations) { - const container = getContainerNode(declaration); + for (let declaration of declarations) { + let container = getContainerNode(declaration); if (!container) { return undefined; @@ -5578,7 +5579,7 @@ namespace ts { } function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, start: number, end: number): number[] { - const positions: number[] = []; + let positions: number[] = []; /// TODO: Cache symbol existence for files to save text search // Also, need to make this work for unicode escapes. @@ -5588,9 +5589,9 @@ namespace ts { return positions; } - const text = sourceFile.text; - const sourceLength = text.length; - const symbolNameLength = symbolName.length; + let text = sourceFile.text; + let sourceLength = text.length; + let symbolNameLength = symbolName.length; let position = text.indexOf(symbolName, start); while (position >= 0) { @@ -5601,7 +5602,7 @@ namespace ts { // We found a match. Make sure it's not part of a larger word (i.e. the char // before and after it have to be a non-identifier char). - const endPosition = position + symbolNameLength; + let endPosition = position + symbolNameLength; if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { @@ -5615,14 +5616,14 @@ namespace ts { } function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { - const references: ReferenceEntry[] = []; - const sourceFile = container.getSourceFile(); - const labelName = targetLabel.text; - const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); + let references: ReferenceEntry[] = []; + let sourceFile = container.getSourceFile(); + let labelName = targetLabel.text; + let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - const node = getTouchingWord(sourceFile, position); + let node = getTouchingWord(sourceFile, position); if (!node || node.getWidth() !== labelName.length) { return; } @@ -5634,14 +5635,14 @@ namespace ts { } }); - const definition: DefinitionInfo = { + let definition: DefinitionInfo = { containerKind: "", containerName: "", fileName: targetLabel.getSourceFile().fileName, kind: ScriptElementKind.label, name: labelName, textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) - }; + } return [{ definition, references }]; } @@ -5686,19 +5687,19 @@ namespace ts { result: ReferencedSymbol[], symbolToIndex: number[]): void { - const sourceFile = container.getSourceFile(); - const tripleSlashDirectivePrefixRegex = /^\/\/\/\s* { cancellationToken.throwIfCancellationRequested(); - const referenceLocation = getTouchingPropertyName(sourceFile, position); + let referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, searchText)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking @@ -5726,14 +5727,14 @@ namespace ts { return; } - const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); + let referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation); if (referenceSymbol) { - const referenceSymbolDeclaration = referenceSymbol.valueDeclaration; - const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); - const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); + let referenceSymbolDeclaration = referenceSymbol.valueDeclaration; + let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); + let relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation); if (relatedSymbol) { - const referencedSymbol = getReferencedSymbol(relatedSymbol); + let referencedSymbol = getReferencedSymbol(relatedSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceLocation)); } /* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment @@ -5743,7 +5744,7 @@ namespace ts { * position of property accessing, the referenceEntry of such position will be handled in the first case. */ else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) { - const referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + let referencedSymbol = getReferencedSymbol(shorthandValueSymbol); referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } @@ -5753,7 +5754,7 @@ namespace ts { return; function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { - const symbolId = getSymbolId(symbol); + let symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { index = result.length; @@ -5772,7 +5773,7 @@ namespace ts { return isInCommentHelper(sourceFile, position, isNonReferenceComment); function isNonReferenceComment(c: CommentRange): boolean { - const commentText = sourceFile.text.substring(c.pos, c.end); + let commentText = sourceFile.text.substring(c.pos, c.end); return !tripleSlashDirectivePrefixRegex.test(commentText); } } @@ -5801,20 +5802,20 @@ namespace ts { return undefined; } - const references: ReferenceEntry[] = []; + let references: ReferenceEntry[] = []; - const sourceFile = searchSpaceNode.getSourceFile(); - const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + let sourceFile = searchSpaceNode.getSourceFile(); + let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - const node = getTouchingWord(sourceFile, position); + let node = getTouchingWord(sourceFile, position); if (!node || node.kind !== SyntaxKind.SuperKeyword) { return; } - const container = getSuperContainer(node, /*includeFunctions*/ false); + let container = getSuperContainer(node, /*includeFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space @@ -5824,7 +5825,7 @@ namespace ts { } }); - const definition = getDefinition(searchSpaceNode.symbol); + let definition = getDefinition(searchSpaceNode.symbol); return [{ definition, references }]; } @@ -5846,7 +5847,7 @@ namespace ts { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - staticFlag &= searchSpaceNode.flags; + staticFlag &= searchSpaceNode.flags searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case SyntaxKind.SourceFile: @@ -5863,7 +5864,7 @@ namespace ts { return undefined; } - const references: ReferenceEntry[] = []; + let references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -5873,7 +5874,7 @@ namespace ts { }); } else { - const sourceFile = searchSpaceNode.getSourceFile(); + let sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } @@ -5894,12 +5895,12 @@ namespace ts { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); - const node = getTouchingWord(sourceFile, position); + let node = getTouchingWord(sourceFile, position); if (!node || (node.kind !== SyntaxKind.ThisKeyword && node.kind !== SyntaxKind.ThisType)) { return; } - const container = getThisContainer(node, /* includeArrowFunctions */ false); + let container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: @@ -5954,13 +5955,13 @@ namespace ts { * property name and variable declaration of the identifier. * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service * should show both 'name' in 'obj' and 'name' in variable declaration - * const name = "Foo"; - * const obj = { name }; + * let name = "Foo"; + * let obj = { name }; * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration * will be included correctly. */ - const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); + let shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(location.parent); if (shorthandValueSymbol) { result.push(shorthandValueSymbol); } @@ -6007,9 +6008,9 @@ namespace ts { function getPropertySymbolFromTypeReference(typeReference: ExpressionWithTypeArguments) { if (typeReference) { - const type = typeChecker.getTypeAtLocation(typeReference); + let type = typeChecker.getTypeAtLocation(typeReference); if (type) { - const propertySymbol = typeChecker.getPropertyOfType(type, propertyName); + let propertySymbol = typeChecker.getPropertyOfType(type, propertyName); if (propertySymbol) { result.push(propertySymbol); } @@ -6029,7 +6030,7 @@ namespace ts { // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { - const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); + let aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol); if (searchSymbols.indexOf(aliasedSymbol) >= 0) { return aliasedSymbol; } @@ -6055,7 +6056,7 @@ namespace ts { // Finally, try all properties with the same name in any type the containing type extended or implemented, and // see if any is in the list if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - const result: Symbol[] = []; + let result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } @@ -6066,21 +6067,21 @@ namespace ts { function getPropertySymbolsFromContextualType(node: Node): Symbol[] { if (isNameOfPropertyAssignment(node)) { - const objectLiteral = node.parent.parent; - const contextualType = typeChecker.getContextualType(objectLiteral); - const name = (node).text; + let objectLiteral = node.parent.parent; + let contextualType = typeChecker.getContextualType(objectLiteral); + let name = (node).text; if (contextualType) { if (contextualType.flags & TypeFlags.Union) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - const unionProperty = contextualType.getProperty(name); + let unionProperty = contextualType.getProperty(name) if (unionProperty) { return [unionProperty]; } else { - const result: Symbol[] = []; + let result: Symbol[] = []; forEach((contextualType).types, t => { - const symbol = t.getProperty(name); + let symbol = t.getProperty(name); if (symbol) { result.push(symbol); } @@ -6089,7 +6090,7 @@ namespace ts { } } else { - const symbol = contextualType.getProperty(name); + let symbol = contextualType.getProperty(name); if (symbol) { return [symbol]; } @@ -6118,8 +6119,8 @@ namespace ts { // Remember the last meaning lastIterationMeaning = meaning; - for (const declaration of declarations) { - const declarationMeaning = getMeaningFromDeclaration(declaration); + for (let declaration of declarations) { + let declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -6154,13 +6155,13 @@ namespace ts { return true; } - const parent = node.parent; + let parent = node.parent; if (parent) { if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) { return true; } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { - const operator = (parent).operatorToken.kind; + let operator = (parent).operatorToken.kind; return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } @@ -6182,8 +6183,8 @@ namespace ts { function getEmitOutput(fileName: string): EmitOutput { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); - const outputFiles: OutputFile[] = []; + let sourceFile = getValidSourceFile(fileName); + let outputFiles: OutputFile[] = []; function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { outputFiles.push({ @@ -6193,7 +6194,7 @@ namespace ts { }); } - const emitOutput = program.emit(sourceFile, writeFile, cancellationToken); + let emitOutput = program.emit(sourceFile, writeFile, cancellationToken); return { outputFiles, @@ -6286,7 +6287,7 @@ namespace ts { } if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { - const decl = root.parent.parent.parent; + let decl = root.parent.parent.parent; return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent).token === SyntaxKind.ImplementsKeyword) || (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent).token === SyntaxKind.ExtendsKeyword); } @@ -6358,7 +6359,7 @@ namespace ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken); } @@ -6369,10 +6370,10 @@ namespace ts { } function getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - const node = getTouchingPropertyName(sourceFile, startPos); + let node = getTouchingPropertyName(sourceFile, startPos); if (!node) { return; @@ -6428,13 +6429,13 @@ namespace ts { function getBreakpointStatementAtPosition(fileName: string, position: number) { // doesn't use compiler - no need to synchronize with host - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName: string): NavigationBarItem[] { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return NavigationBar.getNavigationBarItems(sourceFile, host.getCompilationSettings()); } @@ -6466,11 +6467,11 @@ namespace ts { function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); - const typeChecker = program.getTypeChecker(); + let sourceFile = getValidSourceFile(fileName); + let typeChecker = program.getTypeChecker(); - const result: number[] = []; - const classifiableNames = program.getClassifiableNames(); + let result: number[] = []; + let classifiableNames = program.getClassifiableNames(); processNode(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6482,7 +6483,7 @@ namespace ts { } function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning): ClassificationType { - const flags = symbol.getFlags(); + let flags = symbol.getFlags(); if ((flags & SymbolFlags.Classifiable) === SymbolFlags.None) { return; } @@ -6530,19 +6531,19 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - const kind = node.kind; + let kind = node.kind; checkForClassificationCancellation(kind); if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { - const identifier = node; + let identifier = node; // Only bother calling into the typechecker if this is an identifier that // could possibly resolve to a type name. This makes classification run // in a third of the time it would normally take. if (classifiableNames[identifier.text]) { - const symbol = typeChecker.getSymbolAtLocation(node); + let symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - const type = classifySymbol(symbol, getMeaningFromLocation(node)); + let type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { pushClassification(node.getStart(), node.getWidth(), type); } @@ -6582,8 +6583,8 @@ namespace ts { function convertClassifications(classifications: Classifications): ClassifiedSpan[] { Debug.assert(classifications.spans.length % 3 === 0); - const dense = classifications.spans; - const result: ClassifiedSpan[] = []; + let dense = classifications.spans; + let result: ClassifiedSpan[] = []; for (let i = 0, n = dense.length; i < n; i += 3) { result.push({ textSpan: createTextSpan(dense[i], dense[i + 1]), @@ -6600,15 +6601,15 @@ namespace ts { function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const spanStart = span.start; - const spanLength = span.length; + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let spanStart = span.start; + let spanLength = span.length; // Make a scanner we can get trivia from. - const triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); - const mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text); + let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); + let mergeConflictScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.languageVariant, sourceFile.text); - const result: number[] = []; + let result: number[] = []; processElement(sourceFile); return { spans: result, endOfLineState: EndOfLineState.None }; @@ -6622,15 +6623,15 @@ namespace ts { function classifyLeadingTriviaAndGetTokenStart(token: Node): number { triviaScanner.setTextPos(token.pos); while (true) { - const start = triviaScanner.getTextPos(); + let start = triviaScanner.getTextPos(); // only bother scanning if we have something that could be trivia. if (!couldStartTrivia(sourceFile.text, start)) { return start; } - const kind = triviaScanner.scan(); - const end = triviaScanner.getTextPos(); - const width = end - start; + let kind = triviaScanner.scan(); + let end = triviaScanner.getTextPos(); + let width = end - start; // The moment we get something that isn't trivia, then stop processing. if (!isTrivia(kind)) { @@ -6654,8 +6655,8 @@ namespace ts { } if (kind === SyntaxKind.ConflictMarkerTrivia) { - const text = sourceFile.text; - const ch = text.charCodeAt(start); + let text = sourceFile.text; + let ch = text.charCodeAt(start); // for the <<<<<<< and >>>>>>> markers, we just add them in as comments // in the classification stream. @@ -6676,7 +6677,7 @@ namespace ts { if (kind === SyntaxKind.MultiLineCommentTrivia) { // See if this is a doc comment. If so, we'll classify certain portions of it // specially. - const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); + let docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width); if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDocComment) { docCommentAndDiagnostics.jsDocComment.parent = token; classifyJSDocComment(docCommentAndDiagnostics.jsDocComment); @@ -6695,7 +6696,7 @@ namespace ts { function classifyJSDocComment(docComment: JSDocComment) { let pos = docComment.pos; - for (const tag of docComment.tags) { + for (let tag of docComment.tags) { // As we walk through each tag, classify the portion of text from the end of // the last tag (or the start of the entire doc comment) as 'comment'. if (tag.pos !== pos) { @@ -6753,7 +6754,7 @@ namespace ts { } function processJSDocTemplateTag(tag: JSDocTemplateTag) { - for (const child of tag.getChildren()) { + for (let child of tag.getChildren()) { processElement(child); } } @@ -6775,11 +6776,11 @@ namespace ts { } function classifyDisabledCodeToken() { - const start = mergeConflictScanner.getTextPos(); - const tokenKind = mergeConflictScanner.scan(); - const end = mergeConflictScanner.getTextPos(); + let start = mergeConflictScanner.getTextPos(); + let tokenKind = mergeConflictScanner.scan(); + let end = mergeConflictScanner.getTextPos(); - const type = classifyTokenType(tokenKind); + let type = classifyTokenType(tokenKind); if (type) { pushClassification(start, end - start, type); } @@ -6790,12 +6791,12 @@ namespace ts { return; } - const tokenStart = classifyLeadingTriviaAndGetTokenStart(token); + let tokenStart = classifyLeadingTriviaAndGetTokenStart(token); - const tokenWidth = token.end - tokenStart; + let tokenWidth = token.end - tokenStart; Debug.assert(tokenWidth >= 0); if (tokenWidth > 0) { - const type = classifyTokenType(token.kind, token); + let type = classifyTokenType(token.kind, token); if (type) { pushClassification(tokenStart, tokenWidth, type); } @@ -6922,9 +6923,9 @@ namespace ts { if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) { checkForClassificationCancellation(element.kind); - const children = element.getChildren(sourceFile); + let children = element.getChildren(sourceFile); for (let i = 0, n = children.length; i < n; i++) { - const child = children[i]; + let child = children[i]; if (isToken(child)) { classifyToken(child); } @@ -6939,28 +6940,28 @@ namespace ts { function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return OutliningElementsCollector.collectElements(sourceFile); } function getBraceMatchingAtPosition(fileName: string, position: number) { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const result: TextSpan[] = []; + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let result: TextSpan[] = []; - const token = getTouchingToken(sourceFile, position); + let token = getTouchingToken(sourceFile, position); if (token.getStart(sourceFile) === position) { - const matchKind = getMatchingTokenKind(token); + let matchKind = getMatchingTokenKind(token); // Ensure that there is a corresponding token to match ours. if (matchKind) { - const parentElement = token.parent; + let parentElement = token.parent; - const childNodes = parentElement.getChildren(sourceFile); - for (const current of childNodes) { + let childNodes = parentElement.getChildren(sourceFile); + for (let current of childNodes) { if (current.kind === matchKind) { - const range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); - const range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); + let range1 = createTextSpan(token.getStart(sourceFile), token.getWidth(sourceFile)); + let range2 = createTextSpan(current.getStart(sourceFile), current.getWidth(sourceFile)); // We want to order the braces when we return the result. if (range1.start < range2.start) { @@ -6980,11 +6981,11 @@ namespace ts { function getMatchingTokenKind(token: Node): ts.SyntaxKind { switch (token.kind) { - case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken; + case ts.SyntaxKind.OpenBraceToken: return ts.SyntaxKind.CloseBraceToken case ts.SyntaxKind.OpenParenToken: return ts.SyntaxKind.CloseParenToken; case ts.SyntaxKind.OpenBracketToken: return ts.SyntaxKind.CloseBracketToken; case ts.SyntaxKind.LessThanToken: return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken; + case ts.SyntaxKind.CloseBraceToken: return ts.SyntaxKind.OpenBraceToken case ts.SyntaxKind.CloseParenToken: return ts.SyntaxKind.OpenParenToken; case ts.SyntaxKind.CloseBracketToken: return ts.SyntaxKind.OpenBracketToken; case ts.SyntaxKind.GreaterThanToken: return ts.SyntaxKind.LessThanToken; @@ -6996,29 +6997,29 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); - const result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); + let result = formatting.SmartIndenter.getIndentation(position, sourceFile, editorOptions); log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start)); return result; } function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions): TextChange[] { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatSelection(start, end, sourceFile, getRuleProvider(options), options); } function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[] { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return formatting.formatDocument(sourceFile, getRuleProvider(options), options); } function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[] { - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); if (key === "}") { return formatting.formatOnClosingCurly(position, sourceFile, getRuleProvider(options), options); @@ -7054,16 +7055,16 @@ namespace ts { * be performed. */ function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { - const start = new Date().getTime(); - const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + let start = new Date().getTime(); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return undefined; } - const tokenAtPos = getTokenAtPosition(sourceFile, position); - const tokenStart = tokenAtPos.getStart(); + let tokenAtPos = getTokenAtPosition(sourceFile, position); + let tokenStart = tokenAtPos.getStart() if (!tokenAtPos || tokenStart < position) { return undefined; } @@ -7099,11 +7100,11 @@ namespace ts { return undefined; } - const parameters = getParametersForJsDocOwningNode(commentOwner); - const posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); - const lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + let parameters = getParametersForJsDocOwningNode(commentOwner); + let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - const indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; @@ -7127,7 +7128,7 @@ namespace ts { // * if the caret was directly in front of the object, then we add an extra line and indentation. const preamble = "/**" + newLine + indentationStr + " * "; - const result = + let result = preamble + newLine + docParams + indentationStr + " */" + @@ -7171,7 +7172,7 @@ namespace ts { case SyntaxKind.ArrowFunction: return (rightHandSide).parameters; case SyntaxKind.ClassExpression: - for (const member of (rightHandSide).members) { + for (let member of (rightHandSide).members) { if (member.kind === SyntaxKind.Constructor) { return (member).parameters; } @@ -7191,15 +7192,15 @@ namespace ts { // anything away. synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); + let sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); - const fileContents = sourceFile.text; - const result: TodoComment[] = []; + let fileContents = sourceFile.text; + let result: TodoComment[] = []; if (descriptors.length > 0) { - const regExp = getTodoCommentsRegExp(); + let regExp = getTodoCommentsRegExp(); let matchArray: RegExpExecArray; while (matchArray = regExp.exec(fileContents)) { @@ -7222,15 +7223,15 @@ namespace ts { // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. - const firstDescriptorCaptureIndex = 3; + let firstDescriptorCaptureIndex = 3; Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); - const preamble = matchArray[1]; - const matchPosition = matchArray.index + preamble.length; + let preamble = matchArray[1]; + let matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - const token = getTokenAtPosition(sourceFile, matchPosition); + let token = getTokenAtPosition(sourceFile, matchPosition); if (!isInsideComment(sourceFile, token, matchPosition)) { continue; } @@ -7249,7 +7250,7 @@ namespace ts { continue; } - const message = matchArray[2]; + let message = matchArray[2]; result.push({ descriptor: descriptor, message: message, @@ -7280,14 +7281,14 @@ namespace ts { // // The following three regexps are used to match the start of the text up to the TODO // comment portion. - const singleLineCommentStart = /(?:\/\/+\s*)/.source; - const multiLineCommentStart = /(?:\/\*+\s*)/.source; - const anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; + let singleLineCommentStart = /(?:\/\/+\s*)/.source; + let multiLineCommentStart = /(?:\/\*+\s*)/.source; + let anyNumberOfSpacesAndAsterixesAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. - const preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; + let preamble = "(" + anyNumberOfSpacesAndAsterixesAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: @@ -7297,17 +7298,17 @@ namespace ts { // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + let literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). - const endOfLineOrEndOfComment = /(?:$|\*\/)/.source; - const messageRemainder = /(?:.*?)/.source; + let endOfLineOrEndOfComment = /(?:$|\*\/)/.source + let messageRemainder = /(?:.*?)/.source // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. - const messagePortion = "(" + literals + messageRemainder + ")"; - const regExpString = preamble + messagePortion + endOfLineOrEndOfComment; + let messagePortion = "(" + literals + messageRemainder + ")"; + let regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim @@ -7333,40 +7334,40 @@ namespace ts { function getRenameInfo(fileName: string, position: number): RenameInfo { synchronizeHostData(); - const sourceFile = getValidSourceFile(fileName); - const typeChecker = program.getTypeChecker(); + let sourceFile = getValidSourceFile(fileName); + let typeChecker = program.getTypeChecker(); - const node = getTouchingWord(sourceFile, position); + let node = getTouchingWord(sourceFile, position); // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - const symbol = typeChecker.getSymbolAtLocation(node); + let symbol = typeChecker.getSymbolAtLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol) { - const declarations = symbol.getDeclarations(); + let declarations = symbol.getDeclarations(); if (declarations && declarations.length > 0) { // Disallow rename for elements that are defined in the standard TypeScript library. - const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); + let defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings()); if (defaultLibFileName) { - for (const current of declarations) { - const sourceFile = current.getSourceFile(); - const canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); + for (let current of declarations) { + let sourceFile = current.getSourceFile(); + var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName)); if (sourceFile && getCanonicalFileName(ts.normalizePath(sourceFile.fileName)) === getCanonicalFileName(ts.normalizePath(defaultLibFileName))) { return getRenameInfoError(getLocaleSpecificMessage(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library)); } } } - const displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); - const kind = getSymbolKind(symbol, node); + let displayName = stripQuotes(getDeclaredName(typeChecker, symbol, node)); + let kind = getSymbolKind(symbol, node); if (kind) { return { canRename: true, - kind, - displayName, localizedErrorMessage: undefined, + displayName, fullDisplayName: typeChecker.getFullyQualifiedName(symbol), + kind: kind, kindModifiers: getSymbolModifiers(symbol), triggerSpan: createTextSpan(node.getStart(), node.getWidth()) }; @@ -7433,14 +7434,14 @@ namespace ts { /* @internal */ export function getNameTable(sourceFile: SourceFile): Map { if (!sourceFile.nameTable) { - initializeNameTable(sourceFile); + initializeNameTable(sourceFile) } return sourceFile.nameTable; } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable: Map = {}; + let nameTable: Map = {}; walk(sourceFile); sourceFile.nameTable = nameTable; @@ -7478,13 +7479,13 @@ namespace ts { /// Classifier export function createClassifier(): Classifier { - const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); + let scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false); /// We do not have a full parser support to know when we should parse a regex or not /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where /// we have a series of divide operator. this list allows us to be more accurate by ruling out /// locations where a regexp cannot exist. - const noRegexTable: boolean[] = []; + let noRegexTable: boolean[] = []; noRegexTable[SyntaxKind.Identifier] = true; noRegexTable[SyntaxKind.StringLiteral] = true; noRegexTable[SyntaxKind.NumericLiteral] = true; @@ -7518,7 +7519,7 @@ namespace ts { // // Where on the second line, you will get the 'return' keyword, // a string literal, and a template end consisting of '} } `'. - const templateStack: SyntaxKind[] = []; + let templateStack: SyntaxKind[] = []; /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */ function canFollow(keyword1: SyntaxKind, keyword2: SyntaxKind) { @@ -7544,18 +7545,18 @@ namespace ts { } function convertClassifications(classifications: Classifications, text: string): ClassificationResult { - const entries: ClassificationInfo[] = []; - const dense = classifications.spans; + let entries: ClassificationInfo[] = []; + let dense = classifications.spans; let lastEnd = 0; for (let i = 0, n = dense.length; i < n; i += 3) { - const start = dense[i]; - const length = dense[i + 1]; - const type = dense[i + 2]; + let start = dense[i]; + let length = dense[i + 1]; + let type = dense[i + 2]; // Make a whitespace entry between the last item and this one. if (lastEnd >= 0) { - const whitespaceLength = start - lastEnd; + let whitespaceLength = start - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7565,7 +7566,7 @@ namespace ts { lastEnd = start + length; } - const whitespaceLength = text.length - lastEnd; + let whitespaceLength = text.length - lastEnd; if (whitespaceLength > 0) { entries.push({ length: whitespaceLength, classification: TokenClass.Whitespace }); } @@ -7619,7 +7620,7 @@ namespace ts { // (and a newline). That way when we lex we'll think we're still in a multiline comment. switch (lexState) { case EndOfLineState.InDoubleQuoteStringLiteral: - text = "\"\\\n" + text; + text = '"\\\n' + text; offset = 3; break; case EndOfLineState.InSingleQuoteStringLiteral: @@ -7645,7 +7646,7 @@ namespace ts { scanner.setText(text); - const result: Classifications = { + let result: Classifications = { endOfLineState: EndOfLineState.None, spans: [] }; @@ -7727,7 +7728,7 @@ namespace ts { // If we don't have anything on the template stack, // then we aren't trying to keep track of a previously scanned template head. if (templateStack.length > 0) { - const lastTemplateStackToken = lastOrUndefined(templateStack); + let lastTemplateStackToken = lastOrUndefined(templateStack); if (lastTemplateStackToken === SyntaxKind.TemplateHead) { token = scanner.reScanTemplateToken(); @@ -7757,17 +7758,17 @@ namespace ts { return result; function processToken(): void { - const start = scanner.getTokenPos(); - const end = scanner.getTextPos(); + let start = scanner.getTokenPos(); + let end = scanner.getTextPos(); addResult(start, end, classFromKind(token)); if (end >= text.length) { if (token === SyntaxKind.StringLiteral || token === SyntaxKind.StringLiteralType) { // Check to see if we finished up on a multiline string literal. - const tokenText = scanner.getTokenText(); + let tokenText = scanner.getTokenText(); if (scanner.isUnterminated()) { - const lastCharIndex = tokenText.length - 1; + let lastCharIndex = tokenText.length - 1; let numBackslashes = 0; while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === CharacterCodes.backslash) { @@ -7776,7 +7777,7 @@ namespace ts { // If we have an odd number of backslashes, then the multiline string is unclosed if (numBackslashes & 1) { - const quoteChar = tokenText.charCodeAt(0); + let quoteChar = tokenText.charCodeAt(0); result.endOfLineState = quoteChar === CharacterCodes.doubleQuote ? EndOfLineState.InDoubleQuoteStringLiteral : EndOfLineState.InSingleQuoteStringLiteral; @@ -7825,7 +7826,7 @@ namespace ts { // relative to the original text. start -= offset; end -= offset; - const length = end - start; + let length = end - start; if (length > 0) { result.spans.push(start); @@ -7940,7 +7941,7 @@ namespace ts { } /// getDefaultLibraryFilePath - declare const __dirname: string; + declare let __dirname: string; /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript From a2b6e8c2c0f6e5bf9ac259c16b399791e3f1ca13 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 15 Dec 2015 11:39:54 -0800 Subject: [PATCH 60/75] Use nicer flag collection method --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09760b6b1e5..0700a82a6b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3766,13 +3766,14 @@ namespace ts { function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol { const types = containingType.types; let props: Symbol[]; - let isOptional = !!(containingType.flags & TypeFlags.Intersection); + // Flags we want to propagate to the result if they exist in all source symbols + let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None; for (const current of types) { const type = getApparentType(current); if (type !== unknownType) { const prop = getPropertyOfType(type, name); if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) { - isOptional = isOptional && !!(prop.flags & SymbolFlags.Optional); + commonFlags &= prop.flags; if (!props) { props = [prop]; } @@ -3804,7 +3805,7 @@ namespace ts { SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty | - (isOptional ? SymbolFlags.Optional : SymbolFlags.None), + commonFlags, name); result.containingType = containingType; result.declarations = declarations; From d8db60a9a2be9c4ca82170bc6bb457b70b20f7b5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 15 Dec 2015 17:52:26 -0800 Subject: [PATCH 61/75] Use a comparison function instead of creating a new type for each signature. --- src/compiler/checker.ts | 125 ++++++++++++++++++++++++++++++---------- src/compiler/types.ts | 2 - 2 files changed, 94 insertions(+), 33 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fac21177aae..e1b400310b5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3501,7 +3501,7 @@ namespace ts { function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { for (const s of signatureList) { - if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) { + if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) { return s; } } @@ -4115,16 +4115,6 @@ namespace ts { return signature.erasedSignatureCache; } - function getAnyReturningErasedSignature(signature: Signature): Signature { - if (!signature.anyReturningErasedSignatureCache) { - const erasedSignature = getErasedSignature(signature); - const anyReturningErasedSignature = cloneSignature(erasedSignature); - anyReturningErasedSignature.resolvedReturnType = anyType; - signature.anyReturningErasedSignatureCache = anyReturningErasedSignature; - } - return signature.anyReturningErasedSignatureCache; - } - function getOrCreateTypeFromSignature(signature: Signature): ObjectType { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an @@ -4965,7 +4955,7 @@ namespace ts { return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined); } - function compareTypes(source: Type, target: Type): Ternary { + function compareTypesIdentical(source: Type, target: Type): Ternary { return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False; } @@ -4985,10 +4975,53 @@ namespace ts { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain); } - function isSignatureAssignableTo(source: Signature, target: Signature): boolean { - const sourceType = getOrCreateTypeFromSignature(source); - const targetType = getOrCreateTypeFromSignature(target); - return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined); + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ + function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean { + // TODO (drosen): De-duplicate code between related functions. + if (source === target) { + return true; + } + if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) { + return false; + } + + // Spec 1.0 Section 3.8.3 & 3.8.4: + // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N + source = getErasedSignature(source); + target = getErasedSignature(target); + + const sourceMax = getNumNonRestParameters(source); + const targetMax = getNumNonRestParameters(target); + const checkCount = getNumParametersToCheckForSignatureRelatability(source, sourceMax, target, targetMax); + for (let i = 0; i < checkCount; i++) { + const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + const related = isTypeAssignableTo(t, s) || isTypeAssignableTo(s, t); + if (!related) { + return false; + } + } + + if (!ignoreReturnTypes) { + const targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) { + return true; + } + const sourceReturnType = getReturnTypeOfSignature(source); + + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions + if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) { + if (!(sourceReturnType.flags & TypeFlags.PredicateType)) { + return false; + } + } + + return isTypeAssignableTo(sourceReturnType, targetReturnType); + } + + return true; } function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean { @@ -5002,15 +5035,35 @@ namespace ts { || checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined) || checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) { - // The return types are compatible, so create versions of the signature with 'any' as the return type. - // We need to do this so that we can check assignability while disregarding the return type. - const anyReturningSource = getAnyReturningErasedSignature(implementation); - const anyReturningTarget = getAnyReturningErasedSignature(overload); + return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true); + } - // Create object types to actually perform relation checks. - const anyReturningSourceType = getOrCreateTypeFromSignature(anyReturningSource); - const anyReturningTargetType = getOrCreateTypeFromSignature(anyReturningTarget); - return checkTypeRelatedTo(anyReturningSourceType, anyReturningTargetType, assignableRelation, /*errorNode*/ undefined); + return false; + } + + function getNumNonRestParameters(signature: Signature) { + const numParams = signature.parameters.length; + return signature.hasRestParameter ? + numParams - 1 : + numParams; + } + + function getNumParametersToCheckForSignatureRelatability(source: Signature, sourceNonRestParamCount: number, target: Signature, targetNonRestParamCount: number) { + if (source.hasRestParameter === target.hasRestParameter) { + if (source.hasRestParameter) { + // If both have rest parameters, get the max and add 1 to + // compensate for the rest parameter. + return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1; + } + else { + return Math.min(sourceNonRestParamCount, targetNonRestParamCount); + } + } + else { + // Return the count for whichever signature doesn't have rest parameters. + return source.hasRestParameter ? + targetNonRestParamCount : + sourceNonRestParamCount; } } @@ -5645,7 +5698,11 @@ namespace ts { } } + /** + * See signatureAssignableTo, signatureAssignableTo + */ function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; } @@ -5697,10 +5754,12 @@ namespace ts { } const targetReturnType = getReturnTypeOfSignature(target); - if (targetReturnType === voidType) return result; + if (targetReturnType === voidType) { + return result; + } const sourceReturnType = getReturnTypeOfSignature(source); - // The follow block preserves old behavior forbidding boolean returning functions from being assignable to type guard returning functions + // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) { if (!(sourceReturnType.flags & TypeFlags.PredicateType)) { if (reportErrors) { @@ -5721,7 +5780,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; ++i) { - const related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); + const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -5833,7 +5892,7 @@ namespace ts { } function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean { - return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False; + return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False; } function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary { @@ -5880,7 +5939,11 @@ namespace ts { return false; } - function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + /** + * See signatureRelatedTo, compareSignaturesIdentical + */ + function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + // TODO (drosen): De-duplicate code between related functions. if (source === target) { return Ternary.True; } @@ -7571,7 +7634,7 @@ namespace ts { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) { + else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) { // Signatures aren't identical, do not use return undefined; } @@ -11564,7 +11627,7 @@ namespace ts { } for (const otherSignature of signaturesToCheck) { - if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) { + if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature, /*ignoreReturnTypes*/ false)) { return; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c6c78709300..ff8ffa4ebd2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2280,8 +2280,6 @@ namespace ts { /* @internal */ erasedSignatureCache?: Signature; // Erased version of signature (deferred) /* @internal */ - anyReturningErasedSignatureCache?: Signature; // A version of the erased signature whose type returns 'any' - /* @internal */ isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } From 731925bffeb356e3ee18628bc8d8997d6c79c83f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 15 Dec 2015 20:55:54 -0800 Subject: [PATCH 62/75] Fix linter nits. --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1b400310b5..c017f9e7921 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5040,7 +5040,7 @@ namespace ts { return false; } - + function getNumNonRestParameters(signature: Signature) { const numParams = signature.parameters.length; return signature.hasRestParameter ? @@ -5651,7 +5651,7 @@ namespace ts { shouldElaborateErrors = false; } } - // don't elaborate the primitive apparent types (like Number) + // don't elaborate the primitive apparent types (like Number) // because the actual primitives will have already been reported. if (shouldElaborateErrors && !isPrimitiveApparentType(source)) { reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1, From aa1a7664e73c444a5c9ecf147d85b856f94eee79 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 16 Dec 2015 12:11:24 -0800 Subject: [PATCH 63/75] Add enum/module merge test --- .../enumAssignmentCompat3.errors.txt | 32 +++++++++++++------ .../reference/enumAssignmentCompat3.js | 30 ++++++++++++++++- tests/cases/compiler/enumAssignmentCompat3.ts | 14 +++++++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/tests/baselines/reference/enumAssignmentCompat3.errors.txt b/tests/baselines/reference/enumAssignmentCompat3.errors.txt index c34ad434347..02cb4314777 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.errors.txt +++ b/tests/baselines/reference/enumAssignmentCompat3.errors.txt @@ -1,16 +1,16 @@ -tests/cases/compiler/enumAssignmentCompat3.ts(58,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(68,1): error TS2322: Type 'Abcd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(60,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(70,1): error TS2322: Type 'Cd.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(61,1): error TS2322: Type 'Nope' is not assignable to type 'E'. -tests/cases/compiler/enumAssignmentCompat3.ts(65,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(71,1): error TS2322: Type 'Nope' is not assignable to type 'E'. +tests/cases/compiler/enumAssignmentCompat3.ts(75,1): error TS2322: Type 'First.E' is not assignable to type 'Ab.E'. Property 'c' is missing in type 'Ab.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(66,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'First.E' is not assignable to type 'Cd.E'. Property 'a' is missing in type 'Cd.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(67,1): error TS2322: Type 'E' is not assignable to type 'Nope'. -tests/cases/compiler/enumAssignmentCompat3.ts(72,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(73,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. -tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(77,1): error TS2322: Type 'E' is not assignable to type 'Nope'. +tests/cases/compiler/enumAssignmentCompat3.ts(82,1): error TS2322: Type 'Const.E' is not assignable to type 'First.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(83,1): error TS2322: Type 'First.E' is not assignable to type 'Const.E'. +tests/cases/compiler/enumAssignmentCompat3.ts(86,1): error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. Property 'd' is missing in type 'First.E'. @@ -62,6 +62,15 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. } } + namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } + } + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -71,6 +80,7 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. var k: Const.E; var decl: Decl.E; var merged: Merged.E; + var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' ~~~ @@ -114,4 +124,6 @@ tests/cases/compiler/enumAssignmentCompat3.ts(76,1): error TS2322: Type 'Merged. ~~~ !!! error TS2322: Type 'Merged.E' is not assignable to type 'First.E'. !!! error TS2322: Property 'd' is missing in type 'First.E'. - merged = abc; // ok \ No newline at end of file + merged = abc; // ok + abc = merged2; // ok + merged2 = abc; // ok \ No newline at end of file diff --git a/tests/baselines/reference/enumAssignmentCompat3.js b/tests/baselines/reference/enumAssignmentCompat3.js index e43874911ce..74f74ab1652 100644 --- a/tests/baselines/reference/enumAssignmentCompat3.js +++ b/tests/baselines/reference/enumAssignmentCompat3.js @@ -46,6 +46,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -55,6 +64,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -75,7 +85,9 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok //// [enumAssignmentCompat3.js] var First; @@ -144,6 +156,19 @@ var Merged; })(Merged.E || (Merged.E = {})); var E = Merged.E; })(Merged || (Merged = {})); +var Merged2; +(function (Merged2) { + (function (E) { + E[E["a"] = 0] = "a"; + E[E["b"] = 1] = "b"; + E[E["c"] = 2] = "c"; + })(Merged2.E || (Merged2.E = {})); + var E = Merged2.E; + var E; + (function (E) { + E.d = 5; + })(E = Merged2.E || (Merged2.E = {})); +})(Merged2 || (Merged2 = {})); var abc; var secondAbc; var secondAbcd; @@ -153,6 +178,7 @@ var nope; var k; var decl; var merged; +var merged2; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -172,3 +198,5 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok diff --git a/tests/cases/compiler/enumAssignmentCompat3.ts b/tests/cases/compiler/enumAssignmentCompat3.ts index 33070572661..97a136468e3 100644 --- a/tests/cases/compiler/enumAssignmentCompat3.ts +++ b/tests/cases/compiler/enumAssignmentCompat3.ts @@ -45,6 +45,15 @@ namespace Merged { } } +namespace Merged2 { + export enum E { + a, b, c + } + export module E { + export let d = 5; + } +} + var abc: First.E; var secondAbc: Abc.E; var secondAbcd: Abcd.E; @@ -54,6 +63,7 @@ var nope: Abc.Nope; var k: Const.E; var decl: Decl.E; var merged: Merged.E; +var merged2: Merged2.E; abc = secondAbc; // ok abc = secondAbcd; // missing 'd' abc = secondAb; // ok @@ -74,4 +84,6 @@ k = abc; // merged enums compare all their members abc = merged; // missing 'd' -merged = abc; // ok \ No newline at end of file +merged = abc; // ok +abc = merged2; // ok +merged2 = abc; // ok \ No newline at end of file From a3cce3868b7e7e92eab3ed7cd3b1637087ef137b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 16 Dec 2015 13:19:57 -0800 Subject: [PATCH 64/75] addressed PR feedback --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- .../superInObjectLiterals_ES5.errors.txt | 24 ++++++------- ...ect-literal-getters-and-setters.errors.txt | 12 +++---- tests/cases/fourslash/getOccurrencesSuper3.ts | 34 +++++++++++++++++++ 5 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 tests/cases/fourslash/getOccurrencesSuper3.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2dd567cbe90..8a81ac167b0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7095,7 +7095,7 @@ namespace ts { if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) { if (languageVersion < ScriptTarget.ES6) { - error(node, Diagnostics.super_in_members_of_object_literal_expressions_is_only_allowed_when_option_target_is_ES2015_or_higher); + error(node, Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); return unknownType; } else { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 30b46e5cde2..34552a26b20 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1759,7 +1759,7 @@ "category": "Error", "code": 2658 }, - "'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher.": { + "'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher.": { "category": "Error", "code": 2659 }, diff --git a/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt b/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt index 944766cb5ae..a3149ce8cd5 100644 --- a/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt +++ b/tests/baselines/reference/superInObjectLiterals_ES5.errors.txt @@ -1,12 +1,12 @@ -tests/cases/compiler/superInObjectLiterals_ES5.ts(7,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. -tests/cases/compiler/superInObjectLiterals_ES5.ts(10,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. -tests/cases/compiler/superInObjectLiterals_ES5.ts(14,9): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(7,9): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(10,9): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(14,9): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. tests/cases/compiler/superInObjectLiterals_ES5.ts(17,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superInObjectLiterals_ES5.ts(20,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superInObjectLiterals_ES5.ts(23,9): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. -tests/cases/compiler/superInObjectLiterals_ES5.ts(39,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. -tests/cases/compiler/superInObjectLiterals_ES5.ts(42,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. -tests/cases/compiler/superInObjectLiterals_ES5.ts(46,17): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(39,17): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(42,17): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. +tests/cases/compiler/superInObjectLiterals_ES5.ts(46,17): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. tests/cases/compiler/superInObjectLiterals_ES5.ts(49,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/superInObjectLiterals_ES5.ts(52,17): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. @@ -20,18 +20,18 @@ tests/cases/compiler/superInObjectLiterals_ES5.ts(52,17): error TS2660: 'super' method() { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, get prop() { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. return 10; }, set prop(value) { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, p1: function () { super.method(); @@ -64,18 +64,18 @@ tests/cases/compiler/superInObjectLiterals_ES5.ts(52,17): error TS2660: 'super' method() { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, get prop() { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. return 10; }, set prop(value) { super.method(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, p1: function () { super.method(); diff --git a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt index 16a66bf6fa4..5fe7fa59ff6 100644 --- a/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt +++ b/tests/baselines/reference/super_inside-object-literal-getters-and-setters.errors.txt @@ -1,10 +1,10 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(4,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(5,20): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(5,20): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(7,13): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(8,13): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(8,13): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(11,20): error TS2660: 'super' can only be referenced in members of derived classes or object literal expressions. tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(20,17): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. -tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. ==== tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts (7 errors) ==== @@ -16,14 +16,14 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. return super._foo; ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, set foo(value: string) { ~~~ !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. super._foo = value; ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. }, test: function () { return super._foo; @@ -42,7 +42,7 @@ tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts(21,24): !!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher. return super.test(); ~~~~~ -!!! error TS2659: 'super' in members of object literal expressions is only allowed when option 'target' is 'ES2015' or higher. +!!! error TS2659: 'super' is only allowed in members of object literal expressions when option 'target' is 'ES2015' or higher. } }; } diff --git a/tests/cases/fourslash/getOccurrencesSuper3.ts b/tests/cases/fourslash/getOccurrencesSuper3.ts new file mode 100644 index 00000000000..bceac02a392 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesSuper3.ts @@ -0,0 +1,34 @@ +/// + +////let x = { +//// a() { +//// return [|s/**/uper|].b(); +//// }, +//// b() { +//// return [|super|].a(); +//// }, +//// c: function () { +//// return [|super|].a(); +//// } +//// d: () => [|super|].b(); +////} + +function checkRange(r: FourSlashInterface.Range, expectedOccurences: FourSlashInterface.Range[]): void { + goTo.position(r.start); + if (expectedOccurences.length) { + for (const expected of expectedOccurences) { + verify.occurrencesAtPositionContains(expected); + } + } + else { + verify.occurrencesAtPositionCount(0); + } +} + +let [r0, r1, r2, r3] = test.ranges(); + +checkRange(r0, [r0, r1]); +checkRange(r1, [r0, r1]); +checkRange(r0, [r0, r1]); +checkRange(r2, []); +checkRange(r3, []); \ No newline at end of file From ddbf1030ff5a0b4c0a1c568959c1297663ce9af0 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 16 Dec 2015 16:06:55 -0800 Subject: [PATCH 65/75] Fix fourslash range annotation --- .../fourslash/findAllRefsParameterPropertyDeclaration1.ts | 6 +++--- .../fourslash/findAllRefsParameterPropertyDeclaration2.ts | 6 +++--- .../fourslash/findAllRefsParameterPropertyDeclaration3.ts | 6 +++--- .../cases/fourslash/renameParameterPropertyDeclaration1.ts | 6 +++--- .../cases/fourslash/renameParameterPropertyDeclaration2.ts | 6 +++--- .../cases/fourslash/renameParameterPropertyDeclaration3.ts | 6 +++--- .../cases/fourslash/renameParameterPropertyDeclaration4.ts | 4 ++-- .../cases/fourslash/renameParameterPropertyDeclaration5.ts | 4 ++-- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts index d0854262828..5034a57ae1d 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(private |privateParam|: number) { -//// let localPrivate = |privateParam|; -//// this.|privateParam| += 10; +//// constructor(private [|privateParam|]: number) { +//// let localPrivate = [|privateParam|]; +//// this.[|privateParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts index 7e59567364a..7db5ba13585 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(public |publicParam|: number) { -//// let localPublic = |publicParam|; -//// this.|publicParam| += 10; +//// constructor(public [|publicParam|]: number) { +//// let localPublic = [|publicParam|]; +//// this.[|publicParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts index 2d78e9793f7..c2d8a06f658 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(protected |protectedParam|: number) { -//// let localProtected = |protectedParam|; -//// this.|protectedParam| += 10; +//// constructor(protected [|protectedParam|]: number) { +//// let localProtected = [|protectedParam|]; +//// this.[|protectedParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts index 1faed546d91..4ca09b71e4b 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(private |privateParam|: number) { -//// let localPrivate = |privateParam|; -//// this.|privateParam| += 10; +//// constructor(private [|privateParam|]: number) { +//// let localPrivate = [|privateParam|]; +//// this.[|privateParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts index e8eec5d3a0a..695e3729f94 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(public |publicParam|: number) { -//// let publicParam = |publicParam|; -//// this.|publicParam| += 10; +//// constructor(public [|publicParam|]: number) { +//// let publicParam = [|publicParam|]; +//// this.[|publicParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts index 44f4cf68858..23971f0be27 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts @@ -1,9 +1,9 @@ /// //// class Foo { -//// constructor(protected |protectedParam|: number) { -//// let protectedParam = |protectedParam|; -//// this.|protectedParam| += 10; +//// constructor(protected [|protectedParam|]: number) { +//// let protectedParam = [|protectedParam|]; +//// this.[|protectedParam|] += 10; //// } //// } diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts index 21ba7da4141..4646de6123c 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts @@ -1,8 +1,8 @@ /// //// class Foo { -//// constructor(protected { |protectedParam| }) { -//// let myProtectedParam = |protectedParam|; +//// constructor(protected { [|protectedParam|] }) { +//// let myProtectedParam = [|protectedParam|]; //// } //// } diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts index a4bc00b697b..6d73c7af072 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts @@ -1,8 +1,8 @@ /// //// class Foo { -//// constructor(protected [ |protectedParam| ]) { -//// let myProtectedParam = |protectedParam|; +//// constructor(protected [ [|protectedParam|] ]) { +//// let myProtectedParam = [|protectedParam|]; //// } //// } From 479f7af4df24491ce766f1471c30bd19dab8d86e Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 16 Dec 2015 16:24:18 -0800 Subject: [PATCH 66/75] Add debug fail when getting parameter-property declaration --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d14bb39206..b6f03cd77d1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -442,7 +442,11 @@ namespace ts { const parameterSymbol = getSymbol(constructoDeclaration.locals, parameterName, SymbolFlags.Value); const propertySymbol = getSymbol(classDeclaration.symbol.members, parameterName, SymbolFlags.Value); - return parameterSymbol && propertySymbol ? [parameterSymbol, propertySymbol] : undefined; + if (parameterSymbol && propertySymbol) { + return [parameterSymbol, propertySymbol]; + } + + Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); } function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { From 3558d7d423c6d7837c5a0e7a304ec7edcf100eb0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 17 Dec 2015 11:34:54 -0800 Subject: [PATCH 67/75] Added README.md to 'doc' folder. --- doc/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 doc/README.md diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 00000000000..164fb69ee20 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,7 @@ +This directory contains miscellaneous documentation such as the TypeScript language specification and logo. +If you are looking for more introductory material, you might want to take a look at the [TypeScript Handbook](https://github.com/Microsoft/TypeScript-Handbook). + +# Spec Contributions + +The specification is first authored as a Microsoft Word (docx) file and then generated into Markdown and PDF formats. +Due to the binary format of docx files, and the merging difficulties that may come with it, it is preferred that any suggestions or problems found in the spec should be [filed as issues](https://github.com/Microsoft/TypeScript/issues/new) rather than sent as pull requests. \ No newline at end of file From d59831b4e86b102a28ca045ee0a61778873df1c8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 15:38:02 -0800 Subject: [PATCH 68/75] Get rid of list and map abstractions to reduce GC pressure --- src/compiler/checker.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8d9fe1f7ba5..488549cb180 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,22 +5762,19 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } - const targetNames = arrayToMap(getEnumMembersOfEnumType(target), member => member.name); - for (const member of getEnumMembersOfEnumType(source)) { - if (!hasProperty(targetNames, member.name)) { - reportError(Diagnostics.Property_0_is_missing_in_type_1, - member.name, - typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); - return Ternary.False; + for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { + if (property.flags & SymbolFlags.EnumMember) { + const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { + reportError(Diagnostics.Property_0_is_missing_in_type_1, + property.name, + typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + return Ternary.False; + } } } return Ternary.True; } - - function getEnumMembersOfEnumType(type: Type) { - return filter(resolveStructuredTypeMembers(getTypeOfSymbol(type.symbol)).properties, - property => !!(property.flags & SymbolFlags.EnumMember)); - } } // Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case From 5a53c613e4322d28a9931aca67a10735843cbf16 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 15:51:00 -0800 Subject: [PATCH 69/75] Add assertion to check that ranges-array is not empty so it doesn't silently fail --- src/harness/fourslash.ts | 4 ++++ .../findAllRefsParameterPropertyDeclaration1.ts | 13 ++++++++----- .../findAllRefsParameterPropertyDeclaration2.ts | 1 + .../findAllRefsParameterPropertyDeclaration3.ts | 7 ++++--- tests/cases/fourslash/fourslash.ts | 1 + .../renameParameterPropertyDeclaration1.ts | 3 ++- .../renameParameterPropertyDeclaration2.ts | 3 ++- .../renameParameterPropertyDeclaration3.ts | 3 ++- .../renameParameterPropertyDeclaration4.ts | 3 ++- .../renameParameterPropertyDeclaration5.ts | 3 ++- 10 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 9d729345781..729d2052a92 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2768,6 +2768,10 @@ namespace FourSlashInterface { this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); } + public assertRangesEmpty(ranges: FourSlash.Range[]) { + assert(ranges.length !== 0, "Ranges array is expected to be non-empty"); + } + public completionListIsEmpty() { this.state.verifyCompletionListIsEmpty(this.negative); } diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts index 5034a57ae1d..828b143a4ce 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -7,12 +7,15 @@ //// } //// } -let ranges = test.ranges(); -for (let range of ranges) { +const ranges = test.ranges(); +verify.assertRangesEmpty(ranges); +for (const range of ranges) { goTo.position(range.start); - verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { - verify.referencesAtPositionContains(expectedRange); + if (ranges.length) { + verify.referencesCountIs(ranges.length); + for (const expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } } } \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts index 7db5ba13585..6b15b334c28 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -8,6 +8,7 @@ //// } let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts index c2d8a06f658..1310841eed4 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -7,12 +7,13 @@ //// } //// } -let ranges = test.ranges(); -for (let range of ranges) { +const ranges = test.ranges(); +verify.assertRangesEmpty(ranges); +for (const range of ranges) { goTo.position(range.start); verify.referencesCountIs(ranges.length); - for (let expectedRange of ranges) { + for (const expectedRange of ranges) { verify.referencesAtPositionContains(expectedRange); } } \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index b9b379bd465..fcb221e8233 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -137,6 +137,7 @@ declare namespace FourSlashInterface { verifyDefinitionsName(name: string, containerName: string): void; } class verify extends verifyNegatable { + assertRangesEmpty(ranges: FourSlash.Range[]): void; caretAtMarker(markerName?: string): void; indentationIs(numberOfSpaces: number): void; indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: ts.IndentStyle): void; diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts index 4ca09b71e4b..37db51447ca 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts @@ -7,7 +7,8 @@ //// } //// } -let ranges = test.ranges() +let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts index 695e3729f94..c5e44438ee3 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts @@ -7,7 +7,8 @@ //// } //// } -let ranges = test.ranges() +let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts index 23971f0be27..2ca284f38d9 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts @@ -7,7 +7,8 @@ //// } //// } -let ranges = test.ranges() +let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts index 4646de6123c..35d268532b9 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts @@ -6,7 +6,8 @@ //// } //// } -let ranges = test.ranges() +let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts index 6d73c7af072..d32e69ad0c5 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts @@ -6,7 +6,8 @@ //// } //// } -let ranges = test.ranges() +let ranges = test.ranges(); +verify.assertRangesEmpty(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); From b04bd66bb2a11ddfe7a7c17d35ea87ea4e9160cb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Thu, 17 Dec 2015 16:18:55 -0800 Subject: [PATCH 70/75] Get type of target enum outside the lookup loop --- src/compiler/checker.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 488549cb180..f65a10b266a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5762,9 +5762,10 @@ namespace ts { target.symbol.flags & SymbolFlags.ConstEnum) { return Ternary.False; } + const targetEnumType = getTypeOfSymbol(target.symbol); for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) { if (property.flags & SymbolFlags.EnumMember) { - const targetProperty = getPropertyOfType(getTypeOfSymbol(target.symbol), property.name); + const targetProperty = getPropertyOfType(targetEnumType, property.name); if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { reportError(Diagnostics.Property_0_is_missing_in_type_1, property.name, From e4e6f7072d798c593a0f59eeb2a8d4d9453c3dd1 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 17:27:00 -0800 Subject: [PATCH 71/75] Update assert msg --- src/harness/fourslash.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 729d2052a92..796dc1134a1 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2769,7 +2769,7 @@ namespace FourSlashInterface { } public assertRangesEmpty(ranges: FourSlash.Range[]) { - assert(ranges.length !== 0, "Ranges array is expected to be non-empty"); + assert(ranges.length !== 0, "Array of ranges is expected to be non-empty"); } public completionListIsEmpty() { @@ -3291,4 +3291,4 @@ namespace FourSlashInterface { }; } } -} +} From 2ec97a2d2e5ba40483f2e466ce414cb25e18314c Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 18:00:53 -0800 Subject: [PATCH 72/75] Address PR feed back --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 91bd805a27b..288472a697b 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -925,7 +925,7 @@ var lintTargets = compilerSources .concat(harnessCoreSources) .concat(serverCoreSources) .concat(scriptSources) - .concat([path.join(servicesDirectory,"services.ts")]); + .concat([path.join(servicesDirectory, "services.ts")]); desc("Runs tslint on the compiler sources"); task("lint", ["build-rules"], function() { From 03be649b1c086801c17a84f74a714188c8ae92e7 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 18:14:04 -0800 Subject: [PATCH 73/75] Address feedback --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 796dc1134a1..d5e1687b305 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2768,7 +2768,7 @@ namespace FourSlashInterface { this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); } - public assertRangesEmpty(ranges: FourSlash.Range[]) { + public assertHasRanges(ranges: FourSlash.Range[]) { assert(ranges.length !== 0, "Array of ranges is expected to be non-empty"); } From 7499c7c279933ac2fd35aa5ce11e82d319ec1a59 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 18:34:21 -0800 Subject: [PATCH 74/75] Address feedback --- src/harness/fourslash.ts | 2 +- .../cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts | 2 +- .../cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts | 2 +- .../cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts | 2 +- tests/cases/fourslash/fourslash.ts | 2 +- tests/cases/fourslash/renameParameterPropertyDeclaration1.ts | 2 +- tests/cases/fourslash/renameParameterPropertyDeclaration2.ts | 2 +- tests/cases/fourslash/renameParameterPropertyDeclaration3.ts | 2 +- tests/cases/fourslash/renameParameterPropertyDeclaration4.ts | 2 +- tests/cases/fourslash/renameParameterPropertyDeclaration5.ts | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 796dc1134a1..d5e1687b305 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2768,7 +2768,7 @@ namespace FourSlashInterface { this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative); } - public assertRangesEmpty(ranges: FourSlash.Range[]) { + public assertHasRanges(ranges: FourSlash.Range[]) { assert(ranges.length !== 0, "Array of ranges is expected to be non-empty"); } diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts index 828b143a4ce..4018698f4ef 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -8,7 +8,7 @@ //// } const ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (const range of ranges) { goTo.position(range.start); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts index 6b15b334c28..a450a77e2dc 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -8,7 +8,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts index 1310841eed4..82fd67dfc9b 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -8,7 +8,7 @@ //// } const ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (const range of ranges) { goTo.position(range.start); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index fcb221e8233..dd443e942cf 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -137,7 +137,7 @@ declare namespace FourSlashInterface { verifyDefinitionsName(name: string, containerName: string): void; } class verify extends verifyNegatable { - assertRangesEmpty(ranges: FourSlash.Range[]): void; + assertHasRanges(ranges: FourSlash.Range[]): void; caretAtMarker(markerName?: string): void; indentationIs(numberOfSpaces: number): void; indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: ts.IndentStyle): void; diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts index 37db51447ca..42bfbf63a47 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration1.ts @@ -8,7 +8,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts index c5e44438ee3..e7ef9d1c1a2 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration2.ts @@ -8,7 +8,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts index 2ca284f38d9..9446e2aeb75 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration3.ts @@ -8,7 +8,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts index 35d268532b9..7fb4b8c757d 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration4.ts @@ -7,7 +7,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); diff --git a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts index d32e69ad0c5..b7c47a4c0d7 100644 --- a/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts +++ b/tests/cases/fourslash/renameParameterPropertyDeclaration5.ts @@ -7,7 +7,7 @@ //// } let ranges = test.ranges(); -verify.assertRangesEmpty(ranges); +verify.assertHasRanges(ranges); for (let range of ranges) { goTo.position(range.start); verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); From a5c632cd5a104935a737b58eb41adb79e57cbc84 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 17 Dec 2015 21:08:11 -0800 Subject: [PATCH 75/75] Fix merge error --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index d171724d7ff..4109a4eb345 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5934,7 +5934,7 @@ namespace ts { function populateSearchSymbolSet(symbol: Symbol, location: Node): Symbol[] { // The search set contains at least the current symbol - const result = [symbol]; + let result = [symbol]; // If the symbol is an alias, add what it alaises to the list if (isImportOrExportSpecifierImportSymbol(symbol)) {