diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e13d7dd07bf..fe3009da3aa 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -84,12 +84,13 @@ module ts { if (symbolKind & SymbolFlags.Value && !symbol.valueDeclaration) symbol.valueDeclaration = node; } + // TODO(jfreeman): Implement getDeclarationName for property name function getDeclarationName(node: Declaration): string { if (node.name) { if (node.kind === SyntaxKind.ModuleDeclaration && node.name.kind === SyntaxKind.StringLiteral) { - return '"' + node.name.text + '"'; + return '"' + (node.name).text + '"'; } - return node.name.text; + return (node.name).text; } switch (node.kind) { case SyntaxKind.Constructor: return "__constructor"; @@ -100,7 +101,7 @@ module ts { } function getDisplayName(node: Declaration): string { - return node.name ? identifierToString(node.name) : getDeclarationName(node); + return node.name ? declarationNameToString(node.name) : getDeclarationName(node); } function declareSymbol(symbols: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ae6bacb4c84..2567b54de4a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -431,7 +431,7 @@ module ts { if (!result) { if (nameNotFoundMessage) { - error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : identifierToString(nameArg)); + error(errorLocation, nameNotFoundMessage, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); } return undefined; } @@ -443,7 +443,7 @@ module ts { // to a local variable in the constructor where the code will be emitted. var propertyName = (propertyWithInvalidInitializer).name; error(errorLocation, Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - identifierToString(propertyName), typeof nameArg === "string" ? nameArg : identifierToString(nameArg)); + declarationNameToString(propertyName), typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg)); return undefined; } if (result.flags & SymbolFlags.BlockScopedVariable) { @@ -451,7 +451,7 @@ module ts { var declaration = forEach(result.declarations, d => d.flags & NodeFlags.BlockScoped ? d : undefined); Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined"); if (!isDefinedBefore(declaration, errorLocation)) { - error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, identifierToString(declaration.name)); + error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name)); } } } @@ -483,7 +483,7 @@ module ts { // This function is only for imports with entity names function getSymbolOfPartOfRightHandSideOfImport(entityName: EntityName, importDeclaration?: ImportDeclaration): Symbol { if (!importDeclaration) { - importDeclaration = getAncestor(entityName, SyntaxKind.ImportDeclaration); + importDeclaration = getAncestor(entityName, SyntaxKind.ImportDeclaration); Debug.assert(importDeclaration !== undefined); } // There are three things we might try to look for. In the following examples, @@ -525,7 +525,7 @@ module ts { var symbol = getSymbol(namespace.exports, (name).right.text, meaning); if (!symbol) { error(location, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), - identifierToString((name).right)); + declarationNameToString((name).right)); return; } } @@ -963,11 +963,11 @@ module ts { getNodeLinks(declaration).isVisible = true; if (aliasesToMakeVisible) { if (!contains(aliasesToMakeVisible, declaration)) { - aliasesToMakeVisible.push(declaration); + aliasesToMakeVisible.push(declaration); } } else { - aliasesToMakeVisible = [declaration]; + aliasesToMakeVisible = [declaration]; } return true; } @@ -987,7 +987,7 @@ module ts { var hasNamespaceDeclarationsVisibile = hasVisibleDeclarations(symbolOfNameSpace); return hasNamespaceDeclarationsVisibile ? { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible: hasNamespaceDeclarationsVisibile.aliasesToMakeVisible } : - { accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: identifierToString(firstIdentifier) }; + { accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: declarationNameToString(firstIdentifier) }; } function releaseStringWriter(writer: StringSymbolWriter) { @@ -1060,7 +1060,7 @@ module ts { if (symbol.declarations && symbol.declarations.length > 0) { var declaration = symbol.declarations[0]; if (declaration.name) { - writer.writeSymbol(identifierToString(declaration.name), symbol); + writer.writeSymbol(declarationNameToString(declaration.name), symbol); return; } } @@ -1628,7 +1628,7 @@ module ts { return classType.typeParameters ? createTypeReference(classType, map(classType.typeParameters, _ => anyType)) : classType; } - function getTypeOfVariableDeclaration(declaration: VariableDeclaration): Type { + function getTypeOfVariableOrPropertyDeclaration(declaration: VariableDeclaration | PropertyDeclaration): Type { // A variable declared in a for..in statement is always of type any if (declaration.parent.kind === SyntaxKind.ForInStatement) { return anyType; @@ -1638,7 +1638,7 @@ module ts { return getTypeFromTypeNode(declaration.type); } if (declaration.kind === SyntaxKind.Parameter) { - var func = declaration.parent; + var func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor) { var getter = getDeclarationOfKind(declaration.parent.symbol, SyntaxKind.GetAccessor); @@ -1647,7 +1647,7 @@ module ts { } } // Use contextual parameter type if one is available - var type = getContextuallyTypedParameterType(declaration); + var type = getContextuallyTypedParameterType(declaration); if (type) { return type; } @@ -1695,7 +1695,7 @@ module ts { default: var diagnostic = Diagnostics.Variable_0_implicitly_has_an_1_type; } - error(declaration, diagnostic, identifierToString(declaration.name), typeToString(type)); + error(declaration, diagnostic, declarationNameToString(declaration.name), typeToString(type)); } } @@ -1713,7 +1713,7 @@ module ts { } // Handle variable, parameter or property links.type = resolvingType; - var type = getTypeOfVariableDeclaration(declaration); + var type = getTypeOfVariableOrPropertyDeclaration(declaration); if (links.type === resolvingType) { links.type = type; } @@ -2506,7 +2506,7 @@ module ts { returnType = getAnnotatedAccessorType(setter); } - if (!returnType && !(declaration).body) { + if (!returnType && !(declaration).body) { returnType = anyType; } } @@ -2536,7 +2536,7 @@ module ts { // Don't include signature if node is the implementation of an overloaded function. A node is considered // an implementation node if it has a body and the previous node is of the same kind and immediately // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). - if (i > 0 && (node).body) { + if (i > 0 && (node).body) { var previous = symbol.declarations[i - 1]; if (node.parent === previous.parent && node.kind === previous.kind && node.pos === previous.end) { break; @@ -2558,7 +2558,7 @@ module ts { var type = getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature)); } else { - var type = getReturnTypeFromBody(signature.declaration); + var type = getReturnTypeFromBody(signature.declaration); } if (signature.resolvedReturnType === resolvingType) { signature.resolvedReturnType = type; @@ -2569,7 +2569,7 @@ module ts { if (compilerOptions.noImplicitAny) { var declaration = signature.declaration; if (declaration.name) { - error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, identifierToString(declaration.name)); + error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name)); } else { error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions); @@ -4665,7 +4665,7 @@ module ts { // Return contextual type of parameter or undefined if no contextual type is available function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type { - var func = parameter.parent; + var func = parameter.parent; if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) { if (isContextSensitiveExpression(func)) { var contextualSignature = getContextualSignature(func); @@ -4811,7 +4811,8 @@ module ts { var declaration = node.parent; var objectLiteral = declaration.parent; var type = getContextualType(objectLiteral); - var name = declaration.name.text; + // TODO(jfreeman): Handle this case for computed names and symbols + var name = (declaration.name).text; if (type && name) { return getTypeOfPropertyOfContextualType(type, name) || isNumericName(name) && getIndexTypeOfContextualType(type, IndexKind.Number) || @@ -5078,7 +5079,7 @@ module ts { var prop = getPropertyOfType(apparentType, node.right.text); if (!prop) { if (node.right.text) { - error(node.right, Diagnostics.Property_0_does_not_exist_on_type_1, identifierToString(node.right), typeToString(type)); + error(node.right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(node.right), typeToString(type)); } return unknownType; } @@ -5725,7 +5726,7 @@ module ts { } } - function getReturnTypeFromBody(func: FunctionDeclaration, contextualMapper?: TypeMapper): Type { + function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type { var contextualSignature = getContextualSignature(func); if (func.body.kind !== SyntaxKind.FunctionBlock) { var unwidenedType = checkAndMarkExpression(func.body, contextualMapper); @@ -5759,7 +5760,7 @@ module ts { var typeName = typeToString(widenedType); if (func.name) { - error(func, Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type, identifierToString(func.name), typeName); + error(func, Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type, declarationNameToString(func.name), typeName); } else { error(func, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeName); @@ -5803,7 +5804,7 @@ module ts { // An explicitly typed function whose return type isn't the Void or the Any type // must have at least one return statement somewhere in its body. // An exception to this rule is if the function implementation consists of a single 'throw' statement. - function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionDeclaration, returnType: Type): void { + function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionLikeDeclaration, returnType: Type): void { if (!fullTypeCheck) { return; } @@ -6362,7 +6363,7 @@ module ts { } } else { - if (parameterDeclaration.initializer && !(parameterDeclaration.parent).body) { + if (parameterDeclaration.initializer && !(parameterDeclaration.parent).body) { error(parameterDeclaration, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); } } @@ -6371,16 +6372,16 @@ module ts { function checkReferencesInInitializer(n: Node): void { if (n.kind === SyntaxKind.Identifier) { var referencedSymbol = getNodeLinks(n).resolvedSymbol; - // check FunctionDeclaration.locals (stores parameters\function local variable) + // check FunctionLikeDeclaration.locals (stores parameters\function local variable) // if it contains entry with a specified name and if this entry matches the resolved symbol if (referencedSymbol && referencedSymbol !== unknownSymbol && getSymbol(parameterDeclaration.parent.locals, referencedSymbol.name, SymbolFlags.Value) === referencedSymbol) { if (referencedSymbol.valueDeclaration.kind === SyntaxKind.Parameter) { if (referencedSymbol.valueDeclaration === parameterDeclaration) { - error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, identifierToString(parameterDeclaration.name)); + error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(parameterDeclaration.name)); return; } var enclosingOrReferencedParameter = - forEach((parameterDeclaration.parent).parameters, p => p === parameterDeclaration || p === referencedSymbol.valueDeclaration ? p : undefined); + forEach((parameterDeclaration.parent).parameters, p => p === parameterDeclaration || p === referencedSymbol.valueDeclaration ? p : undefined); if (enclosingOrReferencedParameter === referencedSymbol.valueDeclaration) { // legal case - parameter initializer references some parameter strictly on left of current parameter declaration @@ -6389,7 +6390,7 @@ module ts { // fall through to error reporting } - error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, identifierToString(parameterDeclaration.name), identifierToString(n)); + error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(parameterDeclaration.name), declarationNameToString(n)); } } else { @@ -6654,7 +6655,7 @@ module ts { // TypeScript 1.0 spec (April 2014): 3.7.2.2 // Specialized signatures are not permitted in conjunction with a function body - if ((signatureDeclarationNode).body) { + if ((signatureDeclarationNode).body) { error(signatureDeclarationNode, Diagnostics.A_signature_with_an_implementation_cannot_use_a_string_literal_type); return; } @@ -6705,7 +6706,7 @@ module ts { return; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; @@ -6741,14 +6742,14 @@ module ts { var someNodeFlags: NodeFlags = 0; var allNodeFlags = flagsToCheck; var hasOverloads = false; - var bodyDeclaration: FunctionDeclaration; - var lastSeenNonAmbientDeclaration: FunctionDeclaration; - var previousDeclaration: FunctionDeclaration; + var bodyDeclaration: FunctionLikeDeclaration; + var lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; + var previousDeclaration: FunctionLikeDeclaration; var declarations = symbol.declarations; var isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; - function reportImplementationExpectedError(node: FunctionDeclaration): void { + function reportImplementationExpectedError(node: FunctionLikeDeclaration): void { if (node.name && node.name.kind === SyntaxKind.Missing) { return; } @@ -6764,8 +6765,9 @@ module ts { }); if (subsequentNode) { if (subsequentNode.kind === node.kind) { - var errorNode: Node = (subsequentNode).name || subsequentNode; - if (node.name && (subsequentNode).name && node.name.text === (subsequentNode).name.text) { + var errorNode: Node = (subsequentNode).name || subsequentNode; + // TODO(jfreeman): These are methods, so handle computed name case + if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) { // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members Debug.assert(node.kind === SyntaxKind.Method); Debug.assert((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)); @@ -6773,8 +6775,8 @@ module ts { error(errorNode, diagnostic); return; } - else if ((subsequentNode).body) { - error(errorNode, Diagnostics.Function_implementation_name_must_be_0, identifierToString(node.name)); + else if ((subsequentNode).body) { + error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name)); return; } } @@ -6794,7 +6796,7 @@ module ts { var duplicateFunctionDeclaration = false; var multipleConstructorImplementation = false; for (var i = 0; i < declarations.length; i++) { - var node = declarations[i]; + var node = declarations[i]; var inAmbientContext = isInAmbientContext(node); var inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext; if (inAmbientContextOrInterface) { @@ -6938,7 +6940,7 @@ module ts { // declaration spaces for exported and non-exported declarations intersect forEach(symbol.declarations, d => { if (getDeclarationSpaces(d) & commonDeclarationSpace) { - error(d.name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, identifierToString(d.name)); + error(d.name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(d.name)); } }); } @@ -6965,7 +6967,7 @@ module ts { } } - function checkFunctionDeclaration(node: FunctionDeclaration): void { + function checkFunctionDeclaration(node: FunctionLikeDeclaration): void { checkSignatureDeclaration(node); var symbol = getSymbolOfNode(node); @@ -7001,7 +7003,7 @@ module ts { var typeName = typeToString(anyType); if (node.name) { - error(node, Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type, identifierToString(node.name), typeName); + error(node, Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type, declarationNameToString(node.name), typeName); } else { error(node, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeName); @@ -7016,7 +7018,7 @@ module ts { function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (!hasRestParameters(node) || isInAmbientContext(node) || !(node).body) { + if (!hasRestParameters(node) || isInAmbientContext(node) || !(node).body) { return; } @@ -7037,7 +7039,7 @@ module ts { // - function has implementation (not a signature) // - function has rest parameters // - context is not ambient (otherwise no codegen impact) - if ((node.parent).body && hasRestParameters(node.parent) && !isInAmbientContext(node)) { + if ((node.parent).body && hasRestParameters(node.parent) && !isInAmbientContext(node)) { error(node, Diagnostics.Duplicate_identifier_i_Compiler_uses_i_to_initialize_rest_parameter); } return; @@ -7095,7 +7097,7 @@ module ts { case SyntaxKind.Method: case SyntaxKind.ArrowFunction: case SyntaxKind.Constructor: - if (hasRestParameters(current)) { + if (hasRestParameters(current)) { error(node, Diagnostics.Expression_resolves_to_variable_declaration_i_that_compiler_uses_to_initialize_rest_parameter); return; } @@ -7105,8 +7107,9 @@ module ts { } } - function needCollisionCheckForIdentifier(node: Node, identifier: Identifier, name: string): boolean { - if (!(identifier && identifier.text === name)) { + // TODO(jfreeman): Decide what to do for computed properties + function needCollisionCheckForIdentifier(node: Node, identifier: DeclarationName, name: string): boolean { + if (!(identifier && (identifier).text === name)) { return false; } @@ -7123,15 +7126,16 @@ module ts { return false; } - if (node.kind === SyntaxKind.Parameter && !(node.parent).body) { + if (node.kind === SyntaxKind.Parameter && !(node.parent).body) { // just an overload - no codegen impact return false; } return true; } - - function checkCollisionWithCapturedThisVariable(node: Node, name: Identifier): void { + + // TODO(jfreeman): Decide what to do for computed properties + function checkCollisionWithCapturedThisVariable(node: Node, name: DeclarationName): void { if (!needCollisionCheckForIdentifier(node, name, "_this")) { return; } @@ -7156,7 +7160,7 @@ module ts { } } - function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) { + function checkCollisionWithCapturedSuperVariable(node: Node, name: DeclarationName) { if (!needCollisionCheckForIdentifier(node, name, "_super")) { return; } @@ -7179,7 +7183,8 @@ module ts { } } - function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { + // TODO(jfreeman): Decide what to do for computed properties + function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: DeclarationName) { if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { return; } @@ -7193,7 +7198,8 @@ module ts { var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent; if (parent.kind === SyntaxKind.SourceFile && isExternalModule(parent)) { // If the declaration happens to be in external module, report error that require and exports are reserved keywords - error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, name.text, name.text); + error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, + declarationNameToString(name), declarationNameToString(name)); } } @@ -7229,7 +7235,7 @@ module ts { } } - function checkVariableDeclaration(node: VariableDeclaration) { + function checkVariableDeclaration(node: VariableDeclaration | PropertyDeclaration) { checkSourceElement(node.type); checkExportsOnMergedDeclarations(node); @@ -7243,7 +7249,7 @@ module ts { type = typeOfValueDeclaration; } else { - type = getTypeOfVariableDeclaration(node); + type = getTypeOfVariableOrPropertyDeclaration(node); } @@ -7252,7 +7258,8 @@ module ts { // Use default messages checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*headMessage*/ undefined); } - checkCollisionWithConstDeclarations(node); + //TODO(jfreeman): Check that it is not a computed property + checkCollisionWithConstDeclarations(node); } checkCollisionWithCapturedSuperVariable(node, node.name); @@ -7263,7 +7270,7 @@ module ts { // Multiple declarations for the same variable name in the same declaration space are permitted, // provided that each declaration associates the same type with the variable. if (typeOfValueDeclaration !== unknownType && type !== unknownType && !isTypeIdenticalTo(typeOfValueDeclaration, type)) { - error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, identifierToString(node.name), typeToString(typeOfValueDeclaration), typeToString(type)); + error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, declarationNameToString(node.name), typeToString(typeOfValueDeclaration), typeToString(type)); } } } @@ -7481,16 +7488,17 @@ module ts { } } - function checkTypeNameIsReserved(name: Identifier, message: DiagnosticMessage): void { + // TODO(jfreeman): Decide what to do for computed properties + function checkTypeNameIsReserved(name: DeclarationName, message: DiagnosticMessage): void { // TS 1.0 spec (April 2014): 3.6.1 // The predefined type keywords are reserved and cannot be used as names of user defined types. - switch (name.text) { + switch ((name).text) { case "any": case "number": case "boolean": case "string": case "void": - error(name, message, name.text); + error(name, message, (name).text); } } @@ -7504,7 +7512,7 @@ module ts { if (fullTypeCheck) { for (var j = 0; j < i; j++) { if (typeParameterDeclarations[j].symbol === node.symbol) { - error(node.name, Diagnostics.Duplicate_identifier_0, identifierToString(node.name)); + error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name)); } } } @@ -7762,7 +7770,8 @@ module ts { var enumIsConst = isConstEnumDeclaration(node); forEach(node.members, member => { - if(isNumericName(member.name.text)) { + // TODO(jfreeman): Check that it is not a computed name + if(isNumericName((member.name).text)) { error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } var initializer = member.initializer; @@ -7967,7 +7976,7 @@ module ts { var declarations = symbol.declarations; for (var i = 0; i < declarations.length; i++) { var declaration = declarations[i]; - if ((declaration.kind === SyntaxKind.ClassDeclaration || (declaration.kind === SyntaxKind.FunctionDeclaration && (declaration).body)) && !isInAmbientContext(declaration)) { + if ((declaration.kind === SyntaxKind.ClassDeclaration || (declaration.kind === SyntaxKind.FunctionDeclaration && (declaration).body)) && !isInAmbientContext(declaration)) { return declaration; } } @@ -8028,7 +8037,7 @@ module ts { checkExpression(node.entityName); } else { - error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, identifierToString(moduleName)); + error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName)); } } if (target.flags & SymbolFlags.Type) { @@ -8114,7 +8123,7 @@ module ts { case SyntaxKind.ParenType: return checkSourceElement((node).type); case SyntaxKind.FunctionDeclaration: - return checkFunctionDeclaration(node); + return checkFunctionDeclaration(node); case SyntaxKind.Block: return checkBlock(node); case SyntaxKind.FunctionBlock: @@ -8181,7 +8190,7 @@ module ts { switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - forEach((node).parameters, checkFunctionExpressionBodies); + forEach((node).parameters, checkFunctionExpressionBodies); checkFunctionExpressionBody(node); break; case SyntaxKind.Method: @@ -8189,7 +8198,7 @@ module ts { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.FunctionDeclaration: - forEach((node).parameters, checkFunctionExpressionBodies); + forEach((node).parameters, checkFunctionExpressionBodies); break; case SyntaxKind.WithStatement: checkFunctionExpressionBodies((node).expression); @@ -8471,7 +8480,7 @@ module ts { case SyntaxKind.Method: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return node === (parent).type; + return node === (parent).type; case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: @@ -8727,7 +8736,7 @@ module ts { return true; } - function getLocalNameOfContainer(container: Declaration): string { + function getLocalNameOfContainer(container: ModuleDeclaration | EnumDeclaration): string { var links = getNodeLinks(container); if (!links.localModuleName) { var prefix = ""; @@ -8744,7 +8753,7 @@ module ts { var node = location; while (node) { if ((node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration) && getSymbolOfNode(node) === symbol) { - return getLocalNameOfContainer(node); + return getLocalNameOfContainer(node); } node = node.parent; } @@ -8815,7 +8824,7 @@ module ts { return false; } - function isImplementationOfOverload(node: FunctionDeclaration) { + function isImplementationOfOverload(node: FunctionLikeDeclaration) { if (node.body) { var symbol = getSymbolOfNode(node); var signaturesOfSymbol = getSignaturesOfSymbol(symbol); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1e6f2ed604e..f61d4403eec 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -86,8 +86,9 @@ module ts { var getAccessor: AccessorDeclaration; var setAccessor: AccessorDeclaration; forEach(node.members, (member: Declaration) => { + // TODO(jfreeman): Handle computed names for accessor matching if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor) && - member.name.text === accessor.name.text && + (member.name).text === (accessor.name).text && (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) { if (!firstAccessor) { firstAccessor = member; @@ -577,7 +578,8 @@ module ts { node.kind === SyntaxKind.EnumDeclaration) { // Declaration and has associated name use it if ((node).name) { - scopeName = (node).name.text; + // TODO(jfreeman): Ask shkamat about what this name should be for source maps + scopeName = ((node).name).text; } recordScopeNameStart(scopeName); } @@ -907,15 +909,15 @@ module ts { // This function specifically handles numeric/string literals for enum and accessor 'identifiers'. // In a sense, it does not actually emit identifiers as much as it declares a name for a specific property. - function emitQuotedIdentifier(node: Identifier) { + function emitExpressionForPropertyName(node: DeclarationName) { if (node.kind === SyntaxKind.StringLiteral) { - emitLiteral(node); + emitLiteral(node); } else { write("\""); if (node.kind === SyntaxKind.NumericLiteral) { - write(node.text); + write((node).text); } else { write(getSourceTextOfLocalNode(node)); @@ -1034,7 +1036,7 @@ module ts { function tryEmitConstantValue(node: PropertyAccess | IndexedAccess): boolean { var constantValue = resolver.getConstantValue(node); if (constantValue !== undefined) { - var propertyName = node.kind === SyntaxKind.PropertyAccess ? identifierToString((node).right) : getTextOfNode((node).index); + var propertyName = node.kind === SyntaxKind.PropertyAccess ? declarationNameToString((node).right) : getTextOfNode((node).index); write(constantValue.toString() + " /* " + propertyName + " */"); return true; } @@ -1464,7 +1466,7 @@ module ts { emitTrailingComments(node); } - function emitDefaultValueAssignments(node: FunctionDeclaration) { + function emitDefaultValueAssignments(node: FunctionLikeDeclaration) { forEach(node.parameters, param => { if (param.initializer) { writeLine(); @@ -1484,7 +1486,7 @@ module ts { }); } - function emitRestParameter(node: FunctionDeclaration) { + function emitRestParameter(node: FunctionLikeDeclaration) { if (hasRestParameters(node)) { var restIndex = node.parameters.length - 1; var restParam = node.parameters[restIndex]; @@ -1530,7 +1532,7 @@ module ts { emitTrailingComments(node); } - function emitFunctionDeclaration(node: FunctionDeclaration) { + function emitFunctionDeclaration(node: FunctionLikeDeclaration) { if (!node.body) { return emitPinnedOrTripleSlashComments(node); } @@ -1558,7 +1560,7 @@ module ts { } } - function emitSignatureParameters(node: FunctionDeclaration) { + function emitSignatureParameters(node: FunctionLikeDeclaration) { increaseIndent(); write("("); if (node) { @@ -1568,7 +1570,7 @@ module ts { decreaseIndent(); } - function emitSignatureAndBody(node: FunctionDeclaration) { + function emitSignatureAndBody(node: FunctionLikeDeclaration) { emitSignatureParameters(node); write(" {"); scopeEmitStart(node); @@ -1665,7 +1667,8 @@ module ts { }); } - function emitMemberAccess(memberName: Identifier) { + // TODO(jfreeman): Account for computed property name + function emitMemberAccess(memberName: DeclarationName) { if (memberName.kind === SyntaxKind.StringLiteral || memberName.kind === SyntaxKind.NumericLiteral) { write("["); emitNode(memberName); @@ -1738,7 +1741,7 @@ module ts { write(".prototype"); } write(", "); - emitQuotedIdentifier((member).name); + emitExpressionForPropertyName((member).name); emitEnd((member).name); write(", {"); increaseIndent(); @@ -1951,7 +1954,7 @@ module ts { write("["); write(resolver.getLocalNameOfContainer(node)); write("["); - emitQuotedIdentifier(member.name); + emitExpressionForPropertyName(member.name); write("] = "); if (member.initializer && !isConstEnum) { emit(member.initializer); @@ -1960,7 +1963,7 @@ module ts { write(resolver.getEnumMemberValue(member).toString()); } write("] = "); - emitQuotedIdentifier(member.name); + emitExpressionForPropertyName(member.name); emitEnd(member); write(";"); emitTrailingComments(member); @@ -2072,7 +2075,10 @@ module ts { function getExternalImportDeclarations(node: SourceFile): ImportDeclaration[] { var result: ImportDeclaration[] = []; forEach(node.statements, stat => { - if (stat.kind === SyntaxKind.ImportDeclaration && (stat).externalModuleName && resolver.isReferencedImportDeclaration(stat)) { + if (stat.kind === SyntaxKind.ImportDeclaration + && (stat).externalModuleName + && resolver.isReferencedImportDeclaration(stat)) { + result.push(stat); } }); @@ -2261,7 +2267,7 @@ module ts { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return emitFunctionDeclaration(node); + return emitFunctionDeclaration(node); case SyntaxKind.PrefixOperator: case SyntaxKind.PostfixOperator: return emitUnaryExpression(node); @@ -2504,7 +2510,7 @@ module ts { var getSymbolVisibilityDiagnosticMessage: (symbolAccesibilityResult: SymbolAccessiblityResult) => { errorNode: Node; diagnosticMessage: DiagnosticMessage; - typeName?: Identifier + typeName?: DeclarationName } function createTextWriterWithSymbolWriter(): EmitTextWriterWithSymbolWriter { @@ -2966,11 +2972,12 @@ module ts { function emitPropertyDeclaration(node: PropertyDeclaration) { emitJsDocComments(node); emitDeclarationFlags(node); - emitVariableDeclaration(node); + emitVariableDeclaration(node); write(";"); writeLine(); } + // TODO(jfreeman): Factor out common part of property definition, but treat name differently function emitVariableDeclaration(node: VariableDeclaration) { // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted // so there is no check needed to see if declaration is visible @@ -2998,6 +3005,7 @@ module ts { } // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit else if (node.kind === SyntaxKind.Property) { + // TODO(jfreeman): Deal with computed properties in error reporting. if (node.flags & NodeFlags.Static) { diagnosticMessage = symbolAccesibilityResult.errorModuleName ? symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? @@ -3081,6 +3089,7 @@ module ts { return { diagnosticMessage: diagnosticMessage, errorNode: node.parameters[0], + // TODO(jfreeman): Investigate why we are passing node.name instead of node.parameters[0].name typeName: node.name }; } @@ -3108,7 +3117,7 @@ module ts { } } - function emitFunctionDeclaration(node: FunctionDeclaration) { + function emitFunctionDeclaration(node: FunctionLikeDeclaration) { // If we are emitting Method/Constructor it isn't moduleElement and hence already determined to be emitting // so no need to verify if the declaration is visible if ((node.kind !== SyntaxKind.FunctionDeclaration || resolver.isDeclarationVisible(node)) && @@ -3327,7 +3336,7 @@ module ts { case SyntaxKind.Constructor: case SyntaxKind.FunctionDeclaration: case SyntaxKind.Method: - return emitFunctionDeclaration(node); + return emitFunctionDeclaration(node); case SyntaxKind.ConstructSignature: return emitConstructSignatureDeclaration(node); case SyntaxKind.CallSignature: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5da1952ab27..41243efa171 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -62,9 +62,10 @@ module ts { return identifier.length >= 3 && identifier.charCodeAt(0) === CharacterCodes._ && identifier.charCodeAt(1) === CharacterCodes._ && identifier.charCodeAt(2) === CharacterCodes._ ? identifier.substr(1) : identifier; } + // TODO(jfreeman): Implement declarationNameToString for computed properties // Return display name of an identifier - export function identifierToString(identifier: Identifier) { - return identifier.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(identifier); + export function declarationNameToString(name: DeclarationName) { + return name.kind === SyntaxKind.Missing ? "(Missing)" : getTextOfNode(name); } export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic { @@ -213,11 +214,11 @@ module ts { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: case SyntaxKind.ArrowFunction: - return child((node).name) || - children((node).typeParameters) || - children((node).parameters) || - child((node).type) || - child((node).body); + return child((node).name) || + children((node).typeParameters) || + children((node).parameters) || + child((node).type) || + child((node).body); case SyntaxKind.TypeReference: return child((node).typeName) || children((node).typeArguments); @@ -926,7 +927,7 @@ module ts { } function reportInvalidUseInStrictMode(node: Identifier): void { - // identifierToString cannot be used here since it uses a backreference to 'parent' that is not yet set + // declarationNameToString cannot be used here since it uses a backreference to 'parent' that is not yet set var name = sourceText.substring(skipTrivia(sourceText, node.pos), node.end); grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name); } @@ -1631,7 +1632,7 @@ module ts { // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code // or if its FunctionBody is strict code(11.1.5). // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a - // strict mode FunctionDeclaration or FunctionExpression(13.1) + // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) if (isInStrictMode && isEvalOrArgumentsIdentifier(parameter.name)) { reportInvalidUseInStrictMode(parameter.name); return; @@ -2712,9 +2713,13 @@ module ts { var SetAccesor = 4; var GetOrSetAccessor = GetAccessor | SetAccesor; forEach(node.properties, (p: Declaration) => { + // TODO(jfreeman): continue if we have a computed property if (p.kind === SyntaxKind.OmittedExpression) { return; } + + var name = p.name; + // ECMA-262 11.1.5 Object Initialiser // If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true // a.This production is contained in strict code and IsDataDescriptor(previous) is true and @@ -2737,26 +2742,26 @@ module ts { Debug.fail("Unexpected syntax kind:" + p.kind); } - if (!hasProperty(seen, p.name.text)) { - seen[p.name.text] = currentKind; + if (!hasProperty(seen, name.text)) { + seen[name.text] = currentKind; } else { - var existingKind = seen[p.name.text]; + var existingKind = seen[name.text]; if (currentKind === Property && existingKind === Property) { if (isInStrictMode) { - grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode); + grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name_in_strict_mode); } } else if ((currentKind & GetOrSetAccessor) && (existingKind & GetOrSetAccessor)) { if (existingKind !== GetOrSetAccessor && currentKind !== existingKind) { - seen[p.name.text] = currentKind | existingKind; + seen[name.text] = currentKind | existingKind; } else { - grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); + grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); } } else { - grammarErrorOnNode(p.name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); + grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); } } }); @@ -2771,7 +2776,7 @@ module ts { var body = parseBody(/* ignoreMissingOpenBrace */ false); if (name && isInStrictMode && isEvalOrArgumentsIdentifier(name)) { // It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the - // Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name(13.1) + // Identifier of a FunctionLikeDeclaration or FunctionExpression or as a formal parameter name(13.1) reportInvalidUseInStrictMode(name); } return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, name, sig, body); @@ -3437,8 +3442,8 @@ module ts { return node; } - function parseFunctionDeclaration(pos?: number, flags?: NodeFlags): FunctionDeclaration { - var node = createNode(SyntaxKind.FunctionDeclaration, pos); + function parseFunctionDeclaration(pos?: number, flags?: NodeFlags): FunctionLikeDeclaration { + var node = createNode(SyntaxKind.FunctionDeclaration, pos); if (flags) node.flags = flags; parseExpected(SyntaxKind.FunctionKeyword); node.name = parseIdentifier(); @@ -3447,10 +3452,10 @@ module ts { node.parameters = sig.parameters; node.type = sig.type; node.body = parseAndCheckFunctionBody(/*isConstructor*/ false); - if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name)) { + if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name) && node.name.kind === SyntaxKind.Identifier) { // It is a SyntaxError to use within strict mode code the identifiers eval or arguments as the - // Identifier of a FunctionDeclaration or FunctionExpression or as a formal parameter name(13.1) - reportInvalidUseInStrictMode(node.name); + // Identifier of a FunctionLikeDeclaration or FunctionExpression or as a formal parameter name(13.1) + reportInvalidUseInStrictMode(node.name); } return finishNode(node); } @@ -3567,7 +3572,7 @@ module ts { // A common error is to try to declare an accessor in an ambient class. if (inAmbientContext && canParseSemicolon()) { parseSemicolon(); - node.body = createMissingNode(); + node.body = createMissingNode(); } else { node.body = parseBody(/* ignoreMissingOpenBrace */ false); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index bd9eb8d59e1..973c06d6e2d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -301,34 +301,66 @@ module ts { type?: TypeNode; } + export type DeclarationName = Identifier | LiteralExpression | ComputedPropertyName; + export interface Declaration extends Node { - name?: Identifier; + name?: DeclarationName; + } + + export interface ComputedPropertyName extends Node { + expression: Expression; } export interface TypeParameterDeclaration extends Declaration { + name: Identifier; constraint?: TypeNode; } export interface SignatureDeclaration extends Declaration, ParsedSignature { } export interface VariableDeclaration extends Declaration { + name: Identifier; type?: TypeNode; initializer?: Expression; } - export interface PropertyDeclaration extends VariableDeclaration { } + export interface PropertyDeclaration extends Declaration { + type?: TypeNode; + initializer?: Expression; + } export interface ParameterDeclaration extends VariableDeclaration { } - export interface FunctionDeclaration extends Declaration, ParsedSignature { + /** + * Several node kinds share function-like features such as a signature, + * a name, and a body. These nodes should extend FunctionLikeDeclaration. + * Examples: + * FunctionDeclaration + * MethodDeclaration + * ConstructorDeclaration + * AccessorDeclaration + * FunctionExpression + */ + export interface FunctionLikeDeclaration extends Declaration, ParsedSignature { body?: Block | Expression; } - export interface MethodDeclaration extends FunctionDeclaration { } + export interface FunctionDeclaration extends FunctionLikeDeclaration { + name: Identifier; + body?: Block; + } - export interface ConstructorDeclaration extends FunctionDeclaration { } + export interface MethodDeclaration extends FunctionLikeDeclaration { + body?: Block; + } - export interface AccessorDeclaration extends FunctionDeclaration { } + export interface ConstructorDeclaration extends FunctionLikeDeclaration { + body?: Block; + } + + export interface AccessorDeclaration extends FunctionLikeDeclaration { + body?: Block; + } export interface TypeNode extends Node { } @@ -386,7 +418,8 @@ module ts { whenFalse: Expression; } - export interface FunctionExpression extends Expression, FunctionDeclaration { + export interface FunctionExpression extends Expression, FunctionLikeDeclaration { + name?: Identifier; body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional } @@ -537,6 +570,7 @@ module ts { } export interface ClassDeclaration extends Declaration { + name: Identifier; typeParameters?: NodeArray; baseType?: TypeReferenceNode; implementedTypes?: NodeArray; @@ -544,28 +578,34 @@ module ts { } export interface InterfaceDeclaration extends Declaration { + name: Identifier; typeParameters?: NodeArray; baseTypes?: NodeArray; members: NodeArray; } export interface TypeAliasDeclaration extends Declaration { + name: Identifier; type: TypeNode; } export interface EnumMember extends Declaration { + name: Identifier | LiteralExpression; initializer?: Expression; } export interface EnumDeclaration extends Declaration { + name: Identifier; members: NodeArray; } export interface ModuleDeclaration extends Declaration { + name: Identifier | LiteralExpression; body: Block | ModuleDeclaration; } export interface ImportDeclaration extends Declaration { + name: Identifier; entityName?: EntityName; externalModuleName?: LiteralExpression; } @@ -680,7 +720,7 @@ module ts { getContextualType(node: Node): Type; getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature; - isImplementationOfOverload(node: FunctionDeclaration): boolean; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; hasEarlyErrors(sourceFile?: SourceFile): boolean; @@ -758,7 +798,7 @@ module ts { export interface EmitResolver { getProgram(): Program; - getLocalNameOfContainer(container: Declaration): string; + getLocalNameOfContainer(container: ModuleDeclaration | EnumDeclaration): string; getExpressionNamePrefix(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: ImportDeclaration): boolean; @@ -767,7 +807,7 @@ module ts { getEnumMemberValue(node: EnumMember): number; hasSemanticErrors(): boolean; isDeclarationVisible(node: Declaration): boolean; - isImplementationOfOverload(node: FunctionDeclaration): boolean; + isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult; diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index 3a82e71c677..aa8ec8217ce 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -74,7 +74,7 @@ module ts.BreakpointResolver { return textSpan(node); } - if (node.parent.kind == SyntaxKind.ArrowFunction && (node.parent).body == node) { + if (node.parent.kind == SyntaxKind.ArrowFunction && (node.parent).body == node) { // If this is body of arrow function, it is allowed to have the breakpoint return textSpan(node); } @@ -99,7 +99,7 @@ module ts.BreakpointResolver { case SyntaxKind.Constructor: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return spanInFunctionDeclaration(node); + return spanInFunctionDeclaration(node); case SyntaxKind.FunctionBlock: return spanInFunctionBlock(node); @@ -246,7 +246,7 @@ module ts.BreakpointResolver { } // return type of function go to previous token - if (isAnyFunction(node.parent) && (node.parent).type === node) { + if (isAnyFunction(node.parent) && (node.parent).type === node) { return spanInPreviousNode(node); } @@ -305,7 +305,7 @@ module ts.BreakpointResolver { return textSpan(parameter); } else { - var functionDeclaration = parameter.parent; + var functionDeclaration = parameter.parent; var indexOfParameter = indexOf(functionDeclaration.parameters, parameter); if (indexOfParameter) { // Not a first parameter, go to previous parameter @@ -318,12 +318,12 @@ module ts.BreakpointResolver { } } - function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionDeclaration) { + function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionLikeDeclaration) { return !!(functionDeclaration.flags & NodeFlags.Export) || (functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor); } - function spanInFunctionDeclaration(functionDeclaration: FunctionDeclaration): TypeScript.TextSpan { + function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TypeScript.TextSpan { // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; @@ -340,7 +340,7 @@ module ts.BreakpointResolver { function spanInFunctionBlock(block: Block): TypeScript.TextSpan { var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken(); - if (canFunctionHaveSpanInWholeDeclaration(block.parent)) { + if (canFunctionHaveSpanInWholeDeclaration(block.parent)) { return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index e31c6687428..029df425045 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -361,7 +361,7 @@ module ts.formatting { case SyntaxKind.FunctionExpression: case SyntaxKind.Method: case SyntaxKind.ArrowFunction: - return !(n).body || isCompletedNode((n).body, sourceFile); + return !(n).body || isCompletedNode((n).body, sourceFile); case SyntaxKind.ModuleDeclaration: return (n).body && isCompletedNode((n).body, sourceFile); case SyntaxKind.IfStatement: diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 69180974120..ca06d40fa88 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -73,13 +73,14 @@ module ts.NavigationBar { function sortNodes(nodes: Node[]): Node[] { return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => { if (n1.name && n2.name) { - return n1.name.text.localeCompare(n2.name.text); + // TODO(jfreeman): How do we sort declarations with computed names? + return (n1.name).text.localeCompare((n2.name).text); } else if (n1.name) { return 1; } else if (n2.name) { - -1; + return -1; } else { return n1.kind - n2.kind; @@ -106,7 +107,7 @@ module ts.NavigationBar { break; case SyntaxKind.FunctionDeclaration: - var functionDeclaration = node; + var functionDeclaration = node; if (isTopLevelFunctionDeclaration(functionDeclaration)) { topLevelNodes.push(node); addTopLevelNodes((functionDeclaration.body).statements, topLevelNodes); @@ -116,11 +117,12 @@ module ts.NavigationBar { } } - function isTopLevelFunctionDeclaration(functionDeclaration: FunctionDeclaration) { + function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) { if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) { // A function declaration is 'top level' if it contains any function declarations // within it. if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.FunctionBlock) { + // Proper function declarations can only have identifier names if (forEach((functionDeclaration.body).statements, s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text))) { @@ -230,7 +232,7 @@ module ts.NavigationBar { return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.memberVariableElement); case SyntaxKind.FunctionDeclaration: - return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.functionElement); + return createItem(node, getTextOfNode((node).name), ts.ScriptElementKind.functionElement); case SyntaxKind.VariableDeclaration: if (node.flags & NodeFlags.Const) { @@ -371,8 +373,10 @@ module ts.NavigationBar { }); // Add the constructor parameters in as children of the class (for property parameters). + // Note that *all* parameters will be added to the nodes array, but parameters that + // are not properties will be filtered out later by createChildItem. var nodes: Node[] = constructor - ? constructor.parameters.concat(node.members) + ? node.members.concat(constructor.parameters) : node.members; var childItems = getItemsWorker(sortNodes(nodes), createChildItem); diff --git a/src/services/services.ts b/src/services/services.ts index a5e9b9de10a..d6465084fa4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -628,7 +628,7 @@ module ts { if (this.documentationComment === undefined) { this.documentationComment = this.declaration ? getJsDocCommentsFromDeclarations( [this.declaration], - this.declaration.name ? this.declaration.name.text : "", + /*name*/ undefined, /*canUseParsedParamTagComments*/ false) : []; } @@ -674,7 +674,7 @@ module ts { switch (node.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.Method: - var functionDeclaration = node; + var functionDeclaration = node; if (functionDeclaration.name && functionDeclaration.name.kind !== SyntaxKind.Missing) { var lastDeclaration = namedDeclarations.length > 0 ? @@ -685,7 +685,7 @@ module ts { if (lastDeclaration && functionDeclaration.symbol === lastDeclaration.symbol) { // Overwrite the last declaration if it was an overload // and this one is an implementation. - if (functionDeclaration.body && !(lastDeclaration).body) { + if (functionDeclaration.body && !(lastDeclaration).body) { namedDeclarations[namedDeclarations.length - 1] = functionDeclaration; } } @@ -1963,7 +1963,7 @@ module ts { function isNameOfFunctionDeclaration(node: Node): boolean { return node.kind === SyntaxKind.Identifier && - isAnyFunction(node.parent) && (node.parent).name === node; + isAnyFunction(node.parent) && (node.parent).name === node; } /** Returns true if node is a name of an object literal property, e.g. "a" in x = { "a": 1 } */ @@ -2658,7 +2658,8 @@ module ts { return; } - existingMemberNames[m.name.text] = true; + // TODO(jfreeman): Account for computed property name + existingMemberNames[(m.name).text] = true; }); var filteredMembers: Symbol[] = []; @@ -2945,7 +2946,7 @@ module ts { (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it var signature: Signature; - var functionDeclaration = location.parent; + var functionDeclaration = location.parent; var allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getConstructSignatures() : type.getCallSignatures(); if (!typeResolver.isImplementationOfOverload(functionDeclaration)) { signature = typeResolver.getSignatureFromDeclaration(functionDeclaration); @@ -3225,7 +3226,7 @@ module ts { if ((selectConstructors && d.kind === SyntaxKind.Constructor) || (!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.Method))) { declarations.push(d); - if ((d).body) definition = d; + if ((d).body) definition = d; } }); @@ -3472,7 +3473,7 @@ module ts { } function getReturnOccurrences(returnStatement: ReturnStatement): ReferenceEntry[] { - var func = getContainingFunction(returnStatement); + var func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. if (!(func && hasKind(func.body, SyntaxKind.FunctionBlock))) { @@ -3871,7 +3872,7 @@ module ts { function getNormalizedSymbolName(symbolName: string, declarations: Declaration[]): string { // Special case for function expressions, whose names are solely local to their bodies. - var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined); + var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? d : undefined); if (functionExpression && functionExpression.name) { var name = functionExpression.name.text; @@ -4430,7 +4431,8 @@ module ts { var declarations = sourceFile.getNamedDeclarations(); for (var i = 0, n = declarations.length; i < n; i++) { var declaration = declarations[i]; - var name = declaration.name.text; + // TODO(jfreeman): Skip this declaration if it has a computed name + var name = (declaration.name).text; var matchKind = getMatchKind(searchTerms, name); if (matchKind !== MatchKind.none) { var container = getContainerNode(declaration); @@ -4441,7 +4443,8 @@ module ts { matchKind: MatchKind[matchKind], fileName: filename, textSpan: TypeScript.TextSpan.fromBounds(declaration.getStart(), declaration.getEnd()), - containerName: container.name ? container.name.text : "", + // TODO(jfreeman): What should be the containerName when the container has a computed name? + containerName: container.name ? (container.name).text : "", containerKind: container.name ? getNodeKind(container) : "" }); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 2cc5c827b4f..8dcd06f5621 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -238,7 +238,7 @@ module ts { } if (isAnyFunction(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) { - return (node).typeParameters; + return (node).typeParameters; } return undefined;