merge with master

This commit is contained in:
Vladimir Matveev
2014-10-28 21:49:58 -07:00
403 changed files with 9000 additions and 8486 deletions
+3
View File
@@ -360,6 +360,9 @@ module ts {
case SyntaxKind.InterfaceDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.TypeAliasDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumDeclaration:
bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes, /*isBlockScopeContainer*/ false);
break;
+91 -50
View File
@@ -86,6 +86,7 @@ module ts {
emitFiles: invokeEmitter,
getParentOfSymbol: getParentOfSymbol,
getTypeOfSymbol: getTypeOfSymbol,
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
getPropertiesOfType: getPropertiesOfType,
getPropertyOfType: getPropertyOfType,
getSignaturesOfType: getSignaturesOfType,
@@ -191,6 +192,7 @@ module ts {
if (flags & SymbolFlags.GetAccessor) result |= SymbolFlags.GetAccessorExcludes;
if (flags & SymbolFlags.SetAccessor) result |= SymbolFlags.SetAccessorExcludes;
if (flags & SymbolFlags.TypeParameter) result |= SymbolFlags.TypeParameterExcludes;
if (flags & SymbolFlags.TypeAlias) result |= SymbolFlags.TypeAliasExcludes;
if (flags & SymbolFlags.Import) result |= SymbolFlags.ImportExcludes;
return result;
}
@@ -485,7 +487,7 @@ module ts {
// import a = |b.c|; // Value, type, namespace
// import a = |b.c|.d; // Namespace
if (entityName.kind === SyntaxKind.Identifier && isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
entityName = entityName.parent;
entityName = <QualifiedName>entityName.parent;
}
// Check for case 1 and 3 in the above example
if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) {
@@ -1028,6 +1030,19 @@ module ts {
return result;
}
function getTypeAliasForTypeLiteral(type: Type): Symbol {
if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) {
var node = type.symbol.declarations[0].parent;
while (node.kind === SyntaxKind.ParenType) {
node = node.parent;
}
if (node.kind === SyntaxKind.TypeAliasDeclaration) {
return getSymbolOfNode(node);
}
}
return undefined;
}
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
var _displayBuilder: SymbolDisplayBuilder;
function getSymbolDisplayBuilder(): SymbolDisplayBuilder {
@@ -1218,8 +1233,15 @@ module ts {
writeTypeofSymbol(type);
}
else if (typeStack && contains(typeStack, type)) {
// Recursive usage, use any
writeKeyword(writer, SyntaxKind.AnyKeyword);
// If type is an anonymous type literal in a type alias declaration, use type alias name
var typeAlias = getTypeAliasForTypeLiteral(type);
if (typeAlias) {
buildSymbolDisplay(typeAlias, writer, enclosingDeclaration, SymbolFlags.Type);
}
else {
// Recursive usage, use any
writeKeyword(writer, SyntaxKind.AnyKeyword);
}
}
else {
if (!typeStack) {
@@ -1543,6 +1565,7 @@ module ts {
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ImportDeclaration:
@@ -1946,6 +1969,24 @@ module ts {
return <InterfaceType>links.declaredType;
}
function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
var links = getSymbolLinks(symbol);
if (!links.declaredType) {
links.declaredType = resolvingType;
var declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
var type = getTypeFromTypeNode(declaration.type);
if (links.declaredType === resolvingType) {
links.declaredType = type;
}
}
else if (links.declaredType === resolvingType) {
links.declaredType = unknownType;
var declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
}
return links.declaredType;
}
function getDeclaredTypeOfEnum(symbol: Symbol): Type {
var links = getSymbolLinks(symbol);
if (!links.declaredType) {
@@ -1985,6 +2026,9 @@ module ts {
if (symbol.flags & SymbolFlags.Interface) {
return getDeclaredTypeOfInterface(symbol);
}
if (symbol.flags & SymbolFlags.TypeAlias) {
return getDeclaredTypeOfTypeAlias(symbol);
}
if (symbol.flags & SymbolFlags.Enum) {
return getDeclaredTypeOfEnum(symbol);
}
@@ -3187,19 +3231,18 @@ module ts {
source: Type,
target: Type,
errorNode: Node,
chainedMessage?: DiagnosticMessage,
terminalMessage?: DiagnosticMessage,
headMessage?: DiagnosticMessage,
containingMessageChain?: DiagnosticMessageChain): boolean {
return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, chainedMessage, terminalMessage, containingMessageChain);
return checkTypeRelatedTo(source, target, subtypeRelation, errorNode, headMessage, containingMessageChain);
}
function isTypeAssignableTo(source: Type, target: Type): boolean {
return checkTypeAssignableTo(source, target, /*errorNode*/ undefined);
}
function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, chainedMessage?: DiagnosticMessage, terminalMessage?: DiagnosticMessage): boolean {
return checkTypeRelatedTo(source, target, assignableRelation, errorNode, chainedMessage, terminalMessage);
function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage): boolean {
return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage);
}
function isTypeRelatedTo(source: Type, target: Type, relation: Map<boolean>): boolean {
@@ -3243,7 +3286,7 @@ module ts {
var typeName2 = typeToString(base);
var errorInfo = chainDiagnosticMessages(undefined, Diagnostics.Named_properties_0_of_types_1_and_2_are_not_identical, prop.name, typeName1, typeName2);
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2_Colon, typeToString(type), typeName1, typeName2);
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2);
addDiagnostic(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo, program.getCompilerHost().getNewLine()));
}
}
@@ -3278,8 +3321,7 @@ module ts {
target: Type,
relation: Map<boolean>,
errorNode: Node,
chainedMessage?: DiagnosticMessage,
terminalMessage?: DiagnosticMessage,
headMessage?: DiagnosticMessage,
containingMessageChain?: DiagnosticMessageChain): boolean {
var errorInfo: DiagnosticMessageChain;
@@ -3291,7 +3333,7 @@ module ts {
Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking");
var result = isRelatedToWithCustomErrors(source, target, errorNode !== undefined, chainedMessage, terminalMessage);
var result = isRelatedToWithCustomErrors(source, target, errorNode !== undefined, headMessage);
if (overflow) {
error(errorNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target));
}
@@ -3308,10 +3350,10 @@ module ts {
}
function isRelatedTo(source: Type, target: Type, reportErrors?: boolean): boolean {
return isRelatedToWithCustomErrors(source, target, reportErrors, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
return isRelatedToWithCustomErrors(source, target, reportErrors, /*headMessage*/ undefined);
}
function isRelatedToWithCustomErrors(source: Type, target: Type, reportErrors: boolean, chainedMessage: DiagnosticMessage, terminalMessage: DiagnosticMessage): boolean {
function isRelatedToWithCustomErrors(source: Type, target: Type, reportErrors: boolean, headMessage: DiagnosticMessage): boolean {
if (relation === identityRelation) {
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
if (source === target) return true;
@@ -3363,15 +3405,9 @@ module ts {
}
}
if (reportErrors) {
// The error should end in a period when this is the deepest error in the chain
// (when errorInfo is undefined). Otherwise, it has a colon before the nested
// error.
chainedMessage = chainedMessage || Diagnostics.Type_0_is_not_assignable_to_type_1_Colon;
terminalMessage = terminalMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
var diagnosticKey = errorInfo ? chainedMessage : terminalMessage;
Debug.assert(diagnosticKey);
reportError(diagnosticKey, typeToString(source), typeToString(target));
headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
Debug.assert(headMessage);
reportError(headMessage, typeToString(source), typeToString(target));
}
return false;
}
@@ -3551,7 +3587,7 @@ module ts {
}
if (!isRelatedTo(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp), reportErrors)) {
if (reportErrors) {
reportError(Diagnostics.Types_of_property_0_are_incompatible_Colon, symbolToString(targetProp));
reportError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp));
}
return false;
}
@@ -3657,7 +3693,7 @@ module ts {
if (!isRelatedTo(s, t, reportErrors)) {
if (!isRelatedTo(t, s, false)) {
if (reportErrors) {
reportError(Diagnostics.Types_of_parameters_0_and_1_are_incompatible_Colon,
reportError(Diagnostics.Types_of_parameters_0_and_1_are_incompatible,
source.parameters[i < sourceMax ? i : sourceMax].name,
target.parameters[i < targetMax ? i : targetMax].name);
}
@@ -3701,7 +3737,7 @@ module ts {
}
if (!isRelatedTo(sourceType, targetType, reportErrors)) {
if (reportErrors) {
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
reportError(Diagnostics.Index_signatures_are_incompatible);
}
return false;
}
@@ -3732,7 +3768,7 @@ module ts {
}
if (!compatible) {
if (reportErrors) {
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
reportError(Diagnostics.Index_signatures_are_incompatible);
}
return false;
}
@@ -3825,8 +3861,7 @@ module ts {
// In the following errors, the {1} slot is before the {0} slot because checkTypeSubtypeOf supplies the
// subtype as the first argument to the error
checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation,
Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0_Colon,
checkTypeSubtypeOf(bestSupertypeDownfallType, bestSupertype, errorLocation,
Diagnostics.Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0,
errorMessageChainHead);
}
@@ -5215,7 +5250,7 @@ module ts {
var constraint = getConstraintOfTypeParameter(typeParameters[i]);
if (constraint) {
typeArgumentsAreAssignable = checkTypeAssignableTo(typeArgument, constraint, reportErrors ? typeArgNode : undefined,
Diagnostics.Type_0_does_not_satisfy_the_constraint_1_Colon, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
}
}
@@ -5236,7 +5271,6 @@ module ts {
checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
// Use argument expression as error location when reporting errors
var isValidArgument = checkTypeRelatedTo(argType, paramType, relation, reportErrors ? arg : undefined,
Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1,
Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1);
if (!isValidArgument) {
return false;
@@ -5336,7 +5370,7 @@ module ts {
var inferenceCandidates = resultOfFailedInference.inferences[resultOfFailedInference.failedTypeParameterIndex];
var diagnosticChainHead = chainDiagnosticMessages(/*details*/ undefined, // details will be provided by call to reportNoCommonSupertypeError
Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly_Colon,
Diagnostics.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
typeToString(failedTypeParameter));
reportNoCommonSupertypeError(inferenceCandidates, node.func, diagnosticChainHead);
@@ -5613,7 +5647,7 @@ module ts {
if (fullTypeCheck && targetType !== unknownType) {
var widenedType = getWidenedType(exprType, /*supressNoImplicitAnyErrors*/ true);
if (!(isTypeAssignableTo(targetType, widenedType))) {
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
}
}
return targetType;
@@ -5794,7 +5828,7 @@ module ts {
else {
var exprType = checkExpression(node.body);
if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, undefined, undefined);
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
}
checkFunctionExpressionBodies(node.body);
}
@@ -6100,7 +6134,7 @@ module ts {
// Use default messages
if (ok) {
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
checkTypeAssignableTo(valueType, leftType, node.left, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
checkTypeAssignableTo(valueType, leftType, node.left, /*headMessage*/ undefined);
}
}
}
@@ -6494,7 +6528,7 @@ module ts {
var constraint = getConstraintOfTypeParameter((<TypeReference>type).target.typeParameters[i]);
if (fullTypeCheck && constraint) {
var typeArgument = (<TypeReference>type).typeArguments[i];
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1_Colon, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
}
}
}
@@ -7136,7 +7170,7 @@ module ts {
if (node.initializer) {
if (!(getNodeLinks(node.initializer).flags & NodeCheckFlags.TypeChecked)) {
// Use default messages
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*headMessage*/ undefined);
}
checkCollisionWithConstDeclarations(node);
}
@@ -7249,7 +7283,7 @@ module ts {
func.type ||
(func.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(func.symbol, SyntaxKind.SetAccessor)));
if (checkAssignability) {
checkTypeAssignableTo(checkExpression(node.expression), returnType, node.expression, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
checkTypeAssignableTo(checkExpression(node.expression), returnType, node.expression, /*headMessage*/ undefined);
}
else if (func.kind == SyntaxKind.Constructor) {
// constructor doesn't have explicit return type annotation and yet its return type is known - declaring type
@@ -7277,7 +7311,7 @@ module ts {
var caseType = checkExpression(clause.expression);
if (!isTypeAssignableTo(expressionType, caseType)) {
// check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails
checkTypeAssignableTo(caseType, expressionType, clause.expression, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
checkTypeAssignableTo(caseType, expressionType, clause.expression, /*headMessage*/ undefined);
}
}
checkBlock(clause);
@@ -7414,10 +7448,10 @@ module ts {
if (type.baseTypes.length) {
if (fullTypeCheck) {
var baseType = type.baseTypes[0];
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1_Colon, Diagnostics.Class_0_incorrectly_extends_base_class_1);
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1);
var staticBaseType = getTypeOfSymbol(baseType.symbol);
checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name,
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1_Colon, Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
if (baseType.symbol !== resolveEntityName(node, node.baseType.typeName, SymbolFlags.Value)) {
error(node.baseType, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
}
@@ -7436,7 +7470,7 @@ module ts {
if (t !== unknownType) {
var declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
checkTypeAssignableTo(type, t, node.name, Diagnostics.Class_0_incorrectly_implements_interface_1_Colon, Diagnostics.Class_0_incorrectly_implements_interface_1);
checkTypeAssignableTo(type, t, node.name, Diagnostics.Class_0_incorrectly_implements_interface_1);
}
else {
error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
@@ -7581,7 +7615,7 @@ module ts {
// run subsequent checks only if first set succeeded
if (checkInheritedPropertiesAreIdentical(type, node.name)) {
forEach(type.baseTypes, baseType => {
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1_Colon, Diagnostics.Interface_0_incorrectly_extends_interface_1);
checkTypeAssignableTo(type, baseType, node.name , Diagnostics.Interface_0_incorrectly_extends_interface_1);
});
checkIndexConstraints(type);
}
@@ -7595,6 +7629,10 @@ module ts {
}
}
function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
checkSourceElement(node.type);
}
function computeEnumMemberValues(node: EnumDeclaration) {
var nodeLinks = getNodeLinks(node);
@@ -7621,7 +7659,7 @@ module ts {
// If it is a constant value (not undefined), it is syntactically constrained to be a number.
// Also, we do not need to check this for ambients because there is already
// a syntax error if it is not a constant.
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined);
}
}
}
@@ -7995,6 +8033,8 @@ module ts {
return checkClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.InterfaceDeclaration:
return checkInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.TypeAliasDeclaration:
return checkTypeAliasDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.EnumDeclaration:
return checkEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.ModuleDeclaration:
@@ -8239,6 +8279,7 @@ module ts {
case SyntaxKind.TypeParameter:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
return true;
}
@@ -8325,7 +8366,7 @@ module ts {
function isInRightSideOfImportOrExportAssignment(node: EntityName) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
node = <QualifiedName>node.parent;
}
if (node.parent.kind === SyntaxKind.ImportDeclaration) {
@@ -8359,7 +8400,7 @@ module ts {
}
if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
entityName = entityName.parent;
entityName = <QualifiedName>entityName.parent;
}
if (isExpression(entityName)) {
@@ -8372,7 +8413,7 @@ module ts {
else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccess) {
var symbol = getNodeLinks(entityName).resolvedSymbol;
if (!symbol) {
checkPropertyAccess(<PropertyAccess>entityName);
checkPropertyAccess(<QualifiedName>entityName);
}
return getNodeLinks(entityName).resolvedSymbol;
}
@@ -8404,10 +8445,10 @@ module ts {
return getSymbolOfNode(node.parent);
}
if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(node)) {
if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
return node.parent.kind === SyntaxKind.ExportAssignment
? getSymbolOfEntityName(<Identifier>node)
: getSymbolOfPartOfRightHandSideOfImport(node);
: getSymbolOfPartOfRightHandSideOfImport(<Identifier>node);
}
switch (node.kind) {
@@ -8488,7 +8529,7 @@ module ts {
return symbol && getTypeOfSymbol(symbol);
}
if (isInRightSideOfImportOrExportAssignment(node)) {
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
var symbol = getSymbolInfo(node);
var declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
+4 -3
View File
@@ -183,9 +183,10 @@ module ts {
break;
// If not a primitive, the possible types are specified in what is effectively a map of options.
default:
var value = (args[i++] || "").toLowerCase();
if (hasProperty(opt.type, value)) {
options[opt.name] = opt.type[value];
var map = <Map<number>>opt.type;
var key = (args[i++] || "").toLowerCase();
if (hasProperty(map, key)) {
options[opt.name] = map[key];
}
else {
errors.push(createCompilerDiagnostic(opt.error));
@@ -120,6 +120,7 @@ module ts {
const_declarations_must_be_initialized: { code: 1155, category: DiagnosticCategory.Error, key: "'const' declarations must be initialized" },
const_declarations_can_only_be_declared_inside_a_block: { code: 1156, category: DiagnosticCategory.Error, key: "'const' declarations can only be declared inside a block." },
let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
Aliased_type_cannot_be_an_object_type_literal_Use_an_interface_declaration_instead: { code: 1158, category: DiagnosticCategory.Error, key: "Aliased type cannot be an object type literal. Use an interface declaration instead." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
@@ -140,17 +141,16 @@ module ts {
Global_type_0_must_have_1_type_parameter_s: { code: 2317, category: DiagnosticCategory.Error, key: "Global type '{0}' must have {1} type parameter(s)." },
Cannot_find_global_type_0: { code: 2318, category: DiagnosticCategory.Error, key: "Cannot find global type '{0}'." },
Named_properties_0_of_types_1_and_2_are_not_identical: { code: 2319, category: DiagnosticCategory.Error, key: "Named properties '{0}' of types '{1}' and '{2}' are not identical." },
Interface_0_cannot_simultaneously_extend_types_1_and_2_Colon: { code: 2320, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':" },
Interface_0_cannot_simultaneously_extend_types_1_and_2: { code: 2320, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'." },
Excessive_stack_depth_comparing_types_0_and_1: { code: 2321, category: DiagnosticCategory.Error, key: "Excessive stack depth comparing types '{0}' and '{1}'." },
Type_0_is_not_assignable_to_type_1_Colon: { code: 2322, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}':" },
Type_0_is_not_assignable_to_type_1: { code: 2323, category: DiagnosticCategory.Error, key: "Type '{0}' is not assignable to type '{1}'." },
Property_0_is_missing_in_type_1: { code: 2324, category: DiagnosticCategory.Error, key: "Property '{0}' is missing in type '{1}'." },
Property_0_is_private_in_type_1_but_not_in_type_2: { code: 2325, category: DiagnosticCategory.Error, key: "Property '{0}' is private in type '{1}' but not in type '{2}'." },
Types_of_property_0_are_incompatible_Colon: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible:" },
Types_of_property_0_are_incompatible: { code: 2326, category: DiagnosticCategory.Error, key: "Types of property '{0}' are incompatible." },
Property_0_is_optional_in_type_1_but_required_in_type_2: { code: 2327, category: DiagnosticCategory.Error, key: "Property '{0}' is optional in type '{1}' but required in type '{2}'." },
Types_of_parameters_0_and_1_are_incompatible_Colon: { code: 2328, category: DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible:" },
Types_of_parameters_0_and_1_are_incompatible: { code: 2328, category: DiagnosticCategory.Error, key: "Types of parameters '{0}' and '{1}' are incompatible." },
Index_signature_is_missing_in_type_0: { code: 2329, category: DiagnosticCategory.Error, key: "Index signature is missing in type '{0}'." },
Index_signatures_are_incompatible_Colon: { code: 2330, category: DiagnosticCategory.Error, key: "Index signatures are incompatible:" },
Index_signatures_are_incompatible: { code: 2330, category: DiagnosticCategory.Error, key: "Index signatures are incompatible." },
this_cannot_be_referenced_in_a_module_body: { code: 2331, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in a module body." },
this_cannot_be_referenced_in_current_location: { code: 2332, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in current location." },
this_cannot_be_referenced_in_constructor_arguments: { code: 2333, category: DiagnosticCategory.Error, key: "'this' cannot be referenced in constructor arguments." },
@@ -163,7 +163,6 @@ module ts {
Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword: { code: 2340, category: DiagnosticCategory.Error, key: "Only public and protected methods of the base class are accessible via the 'super' keyword" },
Property_0_is_private_and_only_accessible_within_class_1: { code: 2341, category: DiagnosticCategory.Error, key: "Property '{0}' is private and only accessible within class '{1}'." },
An_index_expression_argument_must_be_of_type_string_number_or_any: { code: 2342, category: DiagnosticCategory.Error, key: "An index expression argument must be of type 'string', 'number', or 'any'." },
Type_0_does_not_satisfy_the_constraint_1_Colon: { code: 2343, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}':" },
Type_0_does_not_satisfy_the_constraint_1: { code: 2344, category: DiagnosticCategory.Error, key: "Type '{0}' does not satisfy the constraint '{1}'." },
Argument_of_type_0_is_not_assignable_to_parameter_of_type_1: { code: 2345, category: DiagnosticCategory.Error, key: "Argument of type '{0}' is not assignable to parameter of type '{1}'." },
Supplied_parameters_do_not_match_any_signature_of_call_target: { code: 2346, category: DiagnosticCategory.Error, key: "Supplied parameters do not match any signature of call target." },
@@ -173,7 +172,6 @@ module ts {
Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon: { code: 2353, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other:" },
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
@@ -234,12 +232,9 @@ module ts {
Numeric_index_type_0_is_not_assignable_to_string_index_type_1: { code: 2413, category: DiagnosticCategory.Error, key: "Numeric index type '{0}' is not assignable to string index type '{1}'." },
Class_name_cannot_be_0: { code: 2414, category: DiagnosticCategory.Error, key: "Class name cannot be '{0}'" },
Class_0_incorrectly_extends_base_class_1: { code: 2415, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}'." },
Class_0_incorrectly_extends_base_class_1_Colon: { code: 2416, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly extends base class '{1}':" },
Class_static_side_0_incorrectly_extends_base_class_static_side_1: { code: 2417, category: DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}'." },
Class_static_side_0_incorrectly_extends_base_class_static_side_1_Colon: { code: 2418, category: DiagnosticCategory.Error, key: "Class static side '{0}' incorrectly extends base class static side '{1}':" },
Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0: { code: 2419, category: DiagnosticCategory.Error, key: "Type name '{0}' in extends clause does not reference constructor function for '{0}'." },
Class_0_incorrectly_implements_interface_1: { code: 2420, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}'." },
Class_0_incorrectly_implements_interface_1_Colon: { code: 2421, category: DiagnosticCategory.Error, key: "Class '{0}' incorrectly implements interface '{1}':" },
A_class_may_only_implement_another_class_or_interface: { code: 2422, category: DiagnosticCategory.Error, key: "A class may only implement another class or interface." },
Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor: { code: 2423, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member accessor." },
Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_property: { code: 2424, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member function '{1}', but extended class '{2}' defines it as instance member property." },
@@ -247,7 +242,6 @@ module ts {
Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function: { code: 2426, category: DiagnosticCategory.Error, key: "Class '{0}' defines instance member accessor '{1}', but extended class '{2}' defines it as instance member function." },
Interface_name_cannot_be_0: { code: 2427, category: DiagnosticCategory.Error, key: "Interface name cannot be '{0}'" },
All_declarations_of_an_interface_must_have_identical_type_parameters: { code: 2428, category: DiagnosticCategory.Error, key: "All declarations of an interface must have identical type parameters." },
Interface_0_incorrectly_extends_interface_1_Colon: { code: 2429, category: DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}':" },
Interface_0_incorrectly_extends_interface_1: { code: 2430, category: DiagnosticCategory.Error, key: "Interface '{0}' incorrectly extends interface '{1}'." },
Enum_name_cannot_be_0: { code: 2431, category: DiagnosticCategory.Error, key: "Enum name cannot be '{0}'" },
In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element: { code: 2432, category: DiagnosticCategory.Error, key: "In an enum with multiple declarations, only one declaration can omit an initializer for its first enum element." },
@@ -271,9 +265,9 @@ module ts {
Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant.", isEarly: true },
Cannot_redeclare_block_scoped_variable_0: { code: 2451, category: DiagnosticCategory.Error, key: "Cannot redeclare block-scoped variable '{0}'.", isEarly: true },
An_enum_member_cannot_have_a_numeric_name: { code: 2452, category: DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly_Colon: { code: 2453, category: DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly:" },
Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0_Colon: { code: 2454, category: DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}':" },
The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly: { code: 2453, category: DiagnosticCategory.Error, key: "The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly." },
Type_argument_candidate_1_is_not_a_valid_type_argument_because_it_is_not_a_supertype_of_candidate_0: { code: 2455, category: DiagnosticCategory.Error, key: "Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'." },
Type_alias_0_circularly_references_itself: { code: 2456, category: DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
@@ -353,9 +347,12 @@ module ts {
Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4076, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from external module {2} but cannot be named." },
Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4077, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
Parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4078, category: DiagnosticCategory.Error, key: "Parameter '{0}' of exported function has or is using private name '{1}'." },
Enum_declarations_must_all_be_const_or_non_const: { code: 4079, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 4079, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
const_enums_can_only_be_used_in_property_access_expressions: { code: 4079, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property access expressions." },
Exported_type_alias_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4079, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
Exported_type_alias_0_has_or_is_using_name_1_from_private_module_2: { code: 4080, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using name '{1}' from private module '{2}'." },
Exported_type_alias_0_has_or_is_using_private_name_1: { code: 4081, category: DiagnosticCategory.Error, key: "Exported type alias '{0}' has or is using private name '{1}'." },
Enum_declarations_must_all_be_const_or_non_const: { code: 4082, category: DiagnosticCategory.Error, key: "Enum declarations must all be const or non-const." },
In_const_enum_declarations_member_initializer_must_be_constant_expression: { code: 4083, category: DiagnosticCategory.Error, key: "In 'const' enum declarations member initializer must be constant expression." },
const_enums_can_only_be_used_in_property_access_expressions: { code: 4084, category: DiagnosticCategory.Error, key: "'const' enums can only be used in property access expressions." },
The_current_host_does_not_support_the_0_option: { code: 5001, category: DiagnosticCategory.Error, key: "The current host does not support the '{0}' option." },
Cannot_find_the_common_subdirectory_path_for_the_input_files: { code: 5009, category: DiagnosticCategory.Error, key: "Cannot find the common subdirectory path for the input files." },
Cannot_read_file_0_Colon_1: { code: 5012, category: DiagnosticCategory.Error, key: "Cannot read file '{0}': {1}" },
+29 -37
View File
@@ -471,6 +471,10 @@
"category": "Error",
"code": 1157
},
"Aliased type cannot be an object type literal. Use an interface declaration instead.": {
"category": "Error",
"code": 1158
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@@ -552,7 +556,7 @@
"category": "Error",
"code": 2319
},
"Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':": {
"Interface '{0}' cannot simultaneously extend types '{1}' and '{2}'.": {
"category": "Error",
"code": 2320
},
@@ -560,7 +564,7 @@
"category": "Error",
"code": 2321
},
"Type '{0}' is not assignable to type '{1}':": {
"Type '{0}' is not assignable to type '{1}'.": {
"category": "Error",
"code": 2322
},
@@ -576,7 +580,7 @@
"category": "Error",
"code": 2325
},
"Types of property '{0}' are incompatible:": {
"Types of property '{0}' are incompatible.": {
"category": "Error",
"code": 2326
},
@@ -584,7 +588,7 @@
"category": "Error",
"code": 2327
},
"Types of parameters '{0}' and '{1}' are incompatible:": {
"Types of parameters '{0}' and '{1}' are incompatible.": {
"category": "Error",
"code": 2328
},
@@ -592,7 +596,7 @@
"category": "Error",
"code": 2329
},
"Index signatures are incompatible:": {
"Index signatures are incompatible.": {
"category": "Error",
"code": 2330
},
@@ -644,10 +648,6 @@
"category": "Error",
"code": 2342
},
"Type '{0}' does not satisfy the constraint '{1}':": {
"category": "Error",
"code": 2343
},
"Type '{0}' does not satisfy the constraint '{1}'.": {
"category": "Error",
"code": 2344
@@ -684,10 +684,6 @@
"category": "Error",
"code": 2352
},
"Neither type '{0}' nor type '{1}' is assignable to the other:": {
"category": "Error",
"code": 2353
},
"No best common type exists among return expressions.": {
"category": "Error",
"code": 2354
@@ -928,18 +924,10 @@
"category": "Error",
"code": 2415
},
"Class '{0}' incorrectly extends base class '{1}':": {
"category": "Error",
"code": 2416
},
"Class static side '{0}' incorrectly extends base class static side '{1}'.": {
"category": "Error",
"code": 2417
},
"Class static side '{0}' incorrectly extends base class static side '{1}':": {
"category": "Error",
"code": 2418
},
"Type name '{0}' in extends clause does not reference constructor function for '{0}'.": {
"category": "Error",
"code": 2419
@@ -948,10 +936,6 @@
"category": "Error",
"code": 2420
},
"Class '{0}' incorrectly implements interface '{1}':": {
"category": "Error",
"code": 2421
},
"A class may only implement another class or interface.": {
"category": "Error",
"code": 2422
@@ -980,10 +964,6 @@
"category": "Error",
"code": 2428
},
"Interface '{0}' incorrectly extends interface '{1}':": {
"category": "Error",
"code": 2429
},
"Interface '{0}' incorrectly extends interface '{1}'.": {
"category": "Error",
"code": 2430
@@ -1080,18 +1060,18 @@
"category": "Error",
"code": 2452
},
"The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly:": {
"The type argument for type parameter '{0}' cannot be inferred from the usage. Consider specifying the type arguments explicitly.": {
"category": "Error",
"code": 2453
},
"Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}':": {
"category": "Error",
"code": 2454
},
"Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'.": {
"category": "Error",
"code": 2455
},
"Type alias '{0}' circularly references itself.": {
"category": "Error",
"code": 2456
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
@@ -1409,17 +1389,29 @@
"category": "Error",
"code": 4078
},
"Enum declarations must all be const or non-const.": {
"Exported type alias '{0}' has or is using name '{1}' from external module {2} but cannot be named.": {
"category": "Error",
"code": 4079
},
"Exported type alias '{0}' has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4080
},
"Exported type alias '{0}' has or is using private name '{1}'.": {
"category": "Error",
"code": 4081
},
"Enum declarations must all be const or non-const.": {
"category": "Error",
"code": 4082
},
"In 'const' enum declarations member initializer must be constant expression.": {
"category": "Error",
"code": 4079
"code": 4083
},
"'const' enums can only be used in property access expressions.": {
"category": "Error",
"code": 4079
"code": 4084
},
"The current host does not support the '{0}' option.": {
"category": "Error",
+28
View File
@@ -2569,6 +2569,32 @@ module ts {
}
}
function emitTypeAliasDeclaration(node: TypeAliasDeclaration) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
emitDeclarationFlags(node);
write("type ");
emitSourceTextOfNode(node.name);
write(" = ");
getSymbolVisibilityDiagnosticMessage = getTypeAliasDeclarationVisibilityError;
resolver.writeTypeAtLocation(node.type, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction, writer);
write(";");
writeLine();
}
function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult) {
var diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Exported_type_alias_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
Diagnostics.Exported_type_alias_0_has_or_is_using_name_1_from_private_module_2 :
Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1;
return {
diagnosticMessage: diagnosticMessage,
errorNode: node,
typeName: node.name
};
}
}
function emitEnumDeclaration(node: EnumDeclaration) {
if (resolver.isDeclarationVisible(node)) {
emitJsDocComments(node);
@@ -3169,6 +3195,8 @@ module ts {
return emitInterfaceDeclaration(<InterfaceDeclaration>node);
case SyntaxKind.ClassDeclaration:
return emitClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.TypeAliasDeclaration:
return emitTypeAliasDeclaration(<TypeAliasDeclaration>node);
case SyntaxKind.EnumMember:
return emitEnumMemberDeclaration(<EnumMember>node);
case SyntaxKind.EnumDeclaration:
+29 -2
View File
@@ -408,6 +408,9 @@ module ts {
children((<InterfaceDeclaration>node).typeParameters) ||
children((<InterfaceDeclaration>node).baseTypes) ||
children((<InterfaceDeclaration>node).members);
case SyntaxKind.TypeAliasDeclaration:
return child((<TypeAliasDeclaration>node).name) ||
child((<TypeAliasDeclaration>node).type);
case SyntaxKind.EnumDeclaration:
return child((<EnumDeclaration>node).name) ||
children((<EnumDeclaration>node).members);
@@ -553,6 +556,7 @@ module ts {
case SyntaxKind.SetAccessor:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
@@ -615,6 +619,7 @@ module ts {
return <ClassDeclaration>node;
case SyntaxKind.EnumDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
// early exit cases - declarations cannot be nested in classes
@@ -1085,7 +1090,6 @@ module ts {
return finishNode(node);
}
error(Diagnostics.Identifier_expected);
var node = <Identifier>createMissingNode();
node.text = "";
return node;
@@ -3178,6 +3182,7 @@ module ts {
case SyntaxKind.ClassKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.TypeKeyword:
// When followed by an identifier, these do not start a statement but might
// instead be following declarations
if (isDeclaration()) {
@@ -3757,7 +3762,25 @@ module ts {
}
return finishNode(node);
}
function parseTypeAliasDeclaration(pos: number, flags: NodeFlags): TypeAliasDeclaration {
var node = <TypeAliasDeclaration>createNode(SyntaxKind.TypeAliasDeclaration, pos);
node.flags = flags;
parseExpected(SyntaxKind.TypeKeyword);
node.name = parseIdentifier();
parseExpected(SyntaxKind.EqualsToken);
node.type = parseType();
parseSemicolon();
var n = node.type;
while (n.kind === SyntaxKind.ParenType) {
n = (<ParenTypeNode>n).type;
}
if (n.kind === SyntaxKind.TypeLiteral && (n.pos !== (<TypeLiteralNode>n).members.pos || n.end !== (<TypeLiteralNode>n).members.end)) {
grammarErrorOnNode(node.type, Diagnostics.Aliased_type_cannot_be_an_object_type_literal_Use_an_interface_declaration_instead);
}
return finishNode(node);
}
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
var enumIsConst = flags & NodeFlags.Const;
function isIntegerLiteral(expression: Expression): boolean {
@@ -3927,6 +3950,7 @@ module ts {
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.ImportKeyword:
case SyntaxKind.TypeKeyword:
// Not true keywords so ensure an identifier follows
return lookAhead(() => nextToken() >= SyntaxKind.Identifier);
case SyntaxKind.ModuleKeyword:
@@ -3992,6 +4016,9 @@ module ts {
case SyntaxKind.InterfaceKeyword:
result = parseInterfaceDeclaration(pos, flags);
break;
case SyntaxKind.TypeKeyword:
result = parseTypeAliasDeclaration(pos, flags);
break;
case SyntaxKind.EnumKeyword:
result = parseAndCheckEnumDeclaration(pos, flags);
break;
+1
View File
@@ -80,6 +80,7 @@ module ts {
"throw": SyntaxKind.ThrowKeyword,
"true": SyntaxKind.TrueKeyword,
"try": SyntaxKind.TryKeyword,
"type": SyntaxKind.TypeKeyword,
"typeof": SyntaxKind.TypeOfKeyword,
"var": SyntaxKind.VarKeyword,
"void": SyntaxKind.VoidKeyword,
+69 -88
View File
@@ -132,6 +132,7 @@ module ts {
NumberKeyword,
SetKeyword,
StringKeyword,
TypeKeyword,
// Parse tree nodes
Missing,
// Names
@@ -202,6 +203,7 @@ module ts {
FunctionBlock,
ClassDeclaration,
InterfaceDeclaration,
TypeAliasDeclaration,
EnumDeclaration,
ModuleDeclaration,
ModuleBlock,
@@ -222,7 +224,7 @@ module ts {
FirstReservedWord = BreakKeyword,
LastReservedWord = WithKeyword,
FirstKeyword = BreakKeyword,
LastKeyword = StringKeyword,
LastKeyword = TypeKeyword,
FirstFutureReservedWord = ImplementsKeyword,
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypeReference,
@@ -230,7 +232,7 @@ module ts {
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken,
FirstToken = EndOfFileToken,
LastToken = StringKeyword,
LastToken = TypeKeyword,
FirstTriviaToken = SingleLineCommentTrivia,
LastTriviaToken = WhitespaceTrivia
}
@@ -280,9 +282,7 @@ module ts {
right: Identifier;
}
export interface EntityName extends Node {
// Identifier, QualifiedName, or Missing
}
export type EntityName = Identifier | QualifiedName;
export interface ParsedSignature {
typeParameters?: NodeArray<TypeParameterDeclaration>;
@@ -310,7 +310,7 @@ module ts {
export interface ParameterDeclaration extends VariableDeclaration { }
export interface FunctionDeclaration extends Declaration, ParsedSignature {
body?: Node; // Block or Expression
body?: Block | Expression;
}
export interface MethodDeclaration extends FunctionDeclaration { }
@@ -376,7 +376,7 @@ module ts {
}
export interface FunctionExpression extends Expression, FunctionDeclaration {
body: Node; // Required, whereas the member inherited from FunctionDeclaration is optional
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
}
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral
@@ -521,6 +521,10 @@ module ts {
members: NodeArray<Node>;
}
export interface TypeAliasDeclaration extends Declaration {
type: TypeNode;
}
export interface EnumMember extends Declaration {
initializer?: Expression;
}
@@ -530,7 +534,7 @@ module ts {
}
export interface ModuleDeclaration extends Declaration {
body: Node; // Block or ModuleDeclaration
body: Block | ModuleDeclaration;
}
export interface ImportDeclaration extends Declaration {
@@ -582,40 +586,24 @@ module ts {
}
export interface SourceMapSpan {
/** Line number in the js file*/
emittedLine: number;
/** Column number in the js file */
emittedColumn: number;
/** Line number in the ts file */
sourceLine: number;
/** Column number in the ts file */
sourceColumn: number;
/** Optional name (index into names array) associated with this span */
nameIndex?: number;
/** ts file (index into sources array) associated with this span*/
sourceIndex: number;
emittedLine: number; // Line number in the .js file
emittedColumn: number; // Column number in the .js file
sourceLine: number; // Line number in the .ts file
sourceColumn: number; // Column number in the .ts file
nameIndex?: number; // Optional name (index into names array) associated with this span
sourceIndex: number; // .ts file (index into sources array) associated with this span*/
}
export interface SourceMapData {
/** Where the sourcemap file is written */
sourceMapFilePath: string;
/** source map URL written in the js file */
jsSourceMappingURL: string;
/** Source map's file field - js file name*/
sourceMapFile: string;
/** Source map's sourceRoot field - location where the sources will be present if not "" */
sourceMapSourceRoot: string;
/** Source map's sources field - list of sources that can be indexed in this source map*/
sourceMapSources: string[];
/** input source file (which one can use on program to get the file)
this is one to one mapping with the sourceMapSources list*/
inputSourceFileNames: string[];
/** Source map's names field - list of names that can be indexed in this source map*/
sourceMapNames?: string[];
/** Source map's mapping field - encoded source map spans*/
sourceMapMappings: string;
/** Raw source map spans that were encoded into the sourceMapMappings*/
sourceMapDecodedMappings: SourceMapSpan[];
sourceMapFilePath: string; // Where the sourcemap file is written
jsSourceMappingURL: string; // source map URL written in the .js file
sourceMapFile: string; // Source map's file field - .js file name
sourceMapSourceRoot: string; // Source map's sourceRoot field - location where the sources will be present if not ""
sourceMapSources: string[]; // Source map's sources field - list of sources that can be indexed in this source map
inputSourceFileNames: string[]; // Input source file (which one can use on program to get the file), 1:1 mapping with the sourceMapSources list
sourceMapNames?: string[]; // Source map's names field - list of names that can be indexed in this source map
sourceMapMappings: string; // Source map's mapping field - encoded source map spans
sourceMapDecodedMappings: SourceMapSpan[]; // Raw source map spans that were encoded into the sourceMapMappings
}
// Return code used by getEmitOutput function to indicate status of the function
@@ -646,6 +634,7 @@ module ts {
emitFiles(targetSourceFile?: SourceFile): EmitResult;
getParentOfSymbol(symbol: Symbol): Symbol;
getTypeOfSymbol(symbol: Symbol): Type;
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
getPropertiesOfType(type: Type): Symbol[];
getPropertyOfType(type: Type, propertyName: string): Symbol;
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
@@ -667,11 +656,8 @@ module ts {
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
hasEarlyErrors(sourceFile?: SourceFile): boolean;
// Returns the constant value of this enum member, or 'undefined' if the enum member has a
// computed value.
// Returns the constant value of this enum member, or 'undefined' if the enum member has a computed value.
getEnumMemberValue(node: EnumMember): number;
isValidPropertyAccess(node: PropertyAccess, propertyName: string): boolean;
getAliasedSymbol(symbol: Symbol): Symbol;
}
@@ -758,64 +744,61 @@ module ts {
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult;
// Returns the constant value this property access resolves to, or 'undefined' if it does
// resolve to a constant.
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: PropertyAccess): number;
hasEarlyErrors(sourceFile?: SourceFile): boolean;
}
export enum SymbolFlags {
FunctionScopedVariable = 0x00000001, // Variable (var) or parameter
Property = 0x00000002, // Property or enum member
EnumMember = 0x00000004, // Enum member
Function = 0x00000008, // Function
Class = 0x00000010, // Class
Interface = 0x00000020, // Interface
Enum = 0x00000040, // Enum
ValueModule = 0x00000080, // Instantiated module
NamespaceModule = 0x00000100, // Uninstantiated module
TypeLiteral = 0x00000200, // Type Literal
ObjectLiteral = 0x00000400, // Object Literal
Method = 0x00000800, // Method
Constructor = 0x00001000, // Constructor
GetAccessor = 0x00002000, // Get accessor
SetAccessor = 0x00004000, // Set accessor
CallSignature = 0x00008000, // Call signature
ConstructSignature = 0x00010000, // Construct signature
IndexSignature = 0x00020000, // Index signature
TypeParameter = 0x00040000, // Type parameter
BlockScopedVariable = 0x00000002, // A block-scoped variable (let or const)
Property = 0x00000004, // Property or enum member
EnumMember = 0x00000008, // Enum member
Function = 0x00000010, // Function
Class = 0x00000020, // Class
Interface = 0x00000040, // Interface
Enum = 0x00000080, // Enum
ValueModule = 0x00000100, // Instantiated module
NamespaceModule = 0x00000200, // Uninstantiated module
TypeLiteral = 0x00000400, // Type Literal
ObjectLiteral = 0x00000800, // Object Literal
Method = 0x00001000, // Method
Constructor = 0x00002000, // Constructor
GetAccessor = 0x00004000, // Get accessor
SetAccessor = 0x00008000, // Set accessor
CallSignature = 0x00010000, // Call signature
ConstructSignature = 0x00020000, // Construct signature
IndexSignature = 0x00040000, // Index signature
TypeParameter = 0x00080000, // Type parameter
TypeAlias = 0x00100000, // Type alias
// Export markers (see comment in declareModuleMember in binder)
ExportValue = 0x00080000, // Exported value marker
ExportType = 0x00100000, // Exported type marker
ExportNamespace = 0x00200000, // Exported namespace marker
ExportValue = 0x00200000, // Exported value marker
ExportType = 0x00400000, // Exported type marker
ExportNamespace = 0x00800000, // Exported namespace marker
Import = 0x00400000, // Import
Instantiated = 0x00800000, // Instantiated symbol
Merged = 0x01000000, // Merged symbol (created during program binding)
Transient = 0x02000000, // Transient symbol (created during type check)
Prototype = 0x04000000, // Prototype property (no source representation)
UnionProperty = 0x08000000, // Property in union type
BlockScopedVariable = 0x10000000, // A block-scoped variable (let ot const)
Import = 0x01000000, // Import
Instantiated = 0x02000000, // Instantiated symbol
Merged = 0x04000000, // Merged symbol (created during program binding)
Transient = 0x08000000, // Transient symbol (created during type check)
Prototype = 0x10000000, // Prototype property (no source representation)
UnionProperty = 0x20000000, // Property in union type
Variable = FunctionScopedVariable | BlockScopedVariable,
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
Namespace = ValueModule | NamespaceModule,
Module = ValueModule | NamespaceModule,
Accessor = GetAccessor | SetAccessor,
Signature = CallSignature | ConstructSignature | IndexSignature,
// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
// same name, or any other value that is not a variable, e.g. ValueModule or Class
FunctionScopedVariableExcludes = Value & ~FunctionScopedVariable,
// Block-scoped declarations are not allowed to be re-declared
// they can not merge with anything in the value space
BlockScopedVariableExcludes = Value,
BlockScopedVariableExcludes = Value,
ParameterExcludes = Value,
PropertyExcludes = Value,
@@ -830,12 +813,10 @@ module ts {
GetAccessorExcludes = Value & ~SetAccessor,
SetAccessorExcludes = Value & ~GetAccessor,
TypeParameterExcludes = Type & ~TypeParameter,
TypeAliasExcludes = Type,
ImportExcludes = Import, // Imports collide with all other imports with the same name
// Imports collide with all other imports with the same name.
ImportExcludes = Import,
ModuleMember = Variable | Function | Class | Interface | Enum | Module | Import,
ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Import,
ExportHasLocal = Function | Class | Enum | ValueModule,
@@ -843,9 +824,9 @@ module ts {
HasExports = Class | Enum | Module,
HasMembers = Class | Interface | TypeLiteral | ObjectLiteral,
IsContainer = HasLocals | HasExports | HasMembers,
PropertyOrAccessor = Property | Accessor,
Export = ExportNamespace | ExportType | ExportValue,
IsContainer = HasLocals | HasExports | HasMembers,
PropertyOrAccessor = Property | Accessor,
Export = ExportNamespace | ExportType | ExportValue,
}
export interface Symbol {
@@ -1095,7 +1076,7 @@ module ts {
target?: ScriptTarget;
version?: boolean;
watch?: boolean;
[option: string]: any;
[option: string]: string | number | boolean;
}
export enum ModuleKind {
@@ -1128,7 +1109,7 @@ module ts {
export interface CommandLineOption {
name: string;
type: any; // "string", "number", "boolean", or an object literal mapping named values to actual values
type: string | Map<number>; // "string", "number", "boolean", or an object literal mapping named values to actual values
shortName?: string; // A short pneumonic for convenience - for instance, 'h' can be used in place of 'help'.
description?: DiagnosticMessage; // The message describing what the command line switch does
paramName?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter.
+1 -1
View File
@@ -108,7 +108,7 @@ module ts.formatting {
function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
// previous token is comma that separates items in list - find the previous item and try to derive indentation from it
var commaItemInfo = findListItemInfo(commaToken);
Debug.assert(commaItemInfo.listItemIndex > 0);
Debug.assert(commaItemInfo && commaItemInfo.listItemIndex > 0);
// The item we're interested in is right before the comma
return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
}
+324 -312
View File
@@ -38,6 +38,7 @@ module ts {
getFullWidth(): number;
getLeadingTriviaWidth(sourceFile?: SourceFile): number;
getFullText(sourceFile?: SourceFile): string;
getText(sourceFile?: SourceFile): string;
getFirstToken(sourceFile?: SourceFile): Node;
getLastToken(sourceFile?: SourceFile): Node;
}
@@ -70,8 +71,6 @@ module ts {
}
export interface SourceFile {
getSourceUnit(): TypeScript.SourceUnitSyntax;
getSyntaxTree(): TypeScript.SyntaxTree;
getScriptSnapshot(): TypeScript.IScriptSnapshot;
getNamedDeclarations(): Declaration[];
update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile;
@@ -130,6 +129,10 @@ module ts {
return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
}
public getText(sourceFile?: SourceFile): string {
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
}
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
scanner.setTextPos(pos);
while (pos < end) {
@@ -655,23 +658,13 @@ module ts {
public languageVersion: ScriptTarget;
public identifiers: Map<string>;
private syntaxTree: TypeScript.SyntaxTree;
private scriptSnapshot: TypeScript.IScriptSnapshot;
private namedDeclarations: Declaration[];
public getSourceUnit(): TypeScript.SourceUnitSyntax {
// If we don't have a script, create one from our parse tree.
return this.getSyntaxTree().sourceUnit();
}
public getScriptSnapshot(): TypeScript.IScriptSnapshot {
return this.scriptSnapshot;
}
public getLineMap(): TypeScript.LineMap {
return this.getSyntaxTree().lineMap();
}
public getNamedDeclarations() {
if (!this.namedDeclarations) {
var sourceFile = this;
@@ -706,6 +699,7 @@ module ts {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
@@ -743,32 +737,11 @@ module ts {
return this.namedDeclarations;
}
public getSyntaxTree(): TypeScript.SyntaxTree {
if (!this.syntaxTree) {
var start = new Date().getTime();
this.syntaxTree = TypeScript.Parser.parse(
this.filename, TypeScript.SimpleText.fromScriptSnapshot(this.scriptSnapshot), this.languageVersion, this.isDeclareFile());
var time = new Date().getTime() - start;
//TypeScript.syntaxTreeParseTime += time;
}
return this.syntaxTree;
}
private isDeclareFile(): boolean {
return TypeScript.isDTSFile(this.filename);
}
public update(scriptSnapshot: TypeScript.IScriptSnapshot, version: string, isOpen: boolean, textChangeRange: TypeScript.TextChangeRange): SourceFile {
// See if we are currently holding onto a syntax tree. We may not be because we're
// either a closed file, or we've just been lazy and haven't had to create the syntax
// tree yet. Access the field instead of the method so we don't accidentally realize
// the old syntax tree.
var oldSyntaxTree = this.syntaxTree;
if (textChangeRange && Debug.shouldAssert(AssertionLevel.Normal)) {
var oldText = this.scriptSnapshot;
var newText = scriptSnapshot;
@@ -786,21 +759,12 @@ module ts {
}
}
var text = TypeScript.SimpleText.fromScriptSnapshot(scriptSnapshot);
// If we don't have a text change, or we don't have an old syntax tree, then do a full
// parse. Otherwise, do an incremental parse.
var newSyntaxTree = !textChangeRange || !oldSyntaxTree
? TypeScript.Parser.parse(this.filename, text, this.languageVersion, TypeScript.isDTSFile(this.filename))
: TypeScript.IncrementalParser.parse(oldSyntaxTree, textChangeRange, text);
return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen, newSyntaxTree);
return SourceFileObject.createSourceFileObject(this.filename, scriptSnapshot, this.languageVersion, version, isOpen);
}
public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean, syntaxTree?: TypeScript.SyntaxTree) {
public static createSourceFileObject(filename: string, scriptSnapshot: TypeScript.IScriptSnapshot, languageVersion: ScriptTarget, version: string, isOpen: boolean) {
var newSourceFile = <SourceFileObject><any>createSourceFile(filename, scriptSnapshot.getText(0, scriptSnapshot.getLength()), languageVersion, version, isOpen);
newSourceFile.scriptSnapshot = scriptSnapshot;
newSourceFile.syntaxTree = syntaxTree;
return newSourceFile;
}
}
@@ -1186,6 +1150,9 @@ module ts {
// interface Y {}
static interfaceElement = "interface";
// type T = ...
static typeElement = "type";
// enum E
static enumElement = "enum";
@@ -1287,7 +1254,6 @@ module ts {
position: number; // position in the file where the completion was requested
entries: CompletionEntry[]; // entries for this completion
symbols: Map<Symbol>; // symbols by entry name map
location: Node; // the node where the completion was requested
typeChecker: TypeChecker; // the typeChecker used to generate this completion
}
@@ -1629,7 +1595,9 @@ module ts {
private initialize(filename: string) {
// ensure that both source file and syntax tree are either initialized or not initialized
Debug.assert(!!this.currentFileSyntaxTree === !!this.currentSourceFile);
var start = new Date().getTime();
this.hostCache = new HostCache(this.host);
this.host.log("SyntaxTreeCache.Initialize: new HostCache: " + (new Date().getTime() - start));
var version = this.hostCache.getVersion(filename);
var syntaxTree: TypeScript.SyntaxTree = null;
@@ -1637,22 +1605,37 @@ module ts {
if (this.currentFileSyntaxTree === null || this.currentFilename !== filename) {
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
var start = new Date().getTime();
syntaxTree = this.createSyntaxTree(filename, scriptSnapshot);
sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true);
this.host.log("SyntaxTreeCache.Initialize: createSyntaxTree: " + (new Date().getTime() - start));
var start = new Date().getTime();
sourceFile = createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true);
this.host.log("SyntaxTreeCache.Initialize: createSourceFile: " + (new Date().getTime() - start));
var start = new Date().getTime();
fixupParentReferences(sourceFile);
this.host.log("SyntaxTreeCache.Initialize: fixupParentRefs : " + (new Date().getTime() - start));
}
else if (this.currentFileVersion !== version) {
var scriptSnapshot = this.hostCache.getScriptSnapshot(filename);
var start = new Date().getTime();
syntaxTree = this.updateSyntaxTree(filename, scriptSnapshot,
this.currentSourceFile.getScriptSnapshot(), this.currentFileSyntaxTree, this.currentFileVersion);
this.host.log("SyntaxTreeCache.Initialize: updateSyntaxTree: " + (new Date().getTime() - start));
var editRange = this.hostCache.getChangeRange(filename, this.currentFileVersion, this.currentSourceFile.getScriptSnapshot());
var start = new Date().getTime();
sourceFile = !editRange
? createSourceFileFromScriptSnapshot(filename, scriptSnapshot, getDefaultCompilerOptions(), version, /*isOpen*/ true)
: this.currentSourceFile.update(scriptSnapshot, version, /*isOpen*/ true, editRange);
this.host.log("SyntaxTreeCache.Initialize: updateSourceFile: " + (new Date().getTime() - start));
var start = new Date().getTime();
fixupParentReferences(sourceFile);
this.host.log("SyntaxTreeCache.Initialize: fixupParentRefs : " + (new Date().getTime() - start));
}
if (syntaxTree !== null) {
@@ -1957,21 +1940,21 @@ module ts {
}
function isRightSideOfPropertyAccess(node: Node) {
return node.parent.kind === SyntaxKind.PropertyAccess && (<PropertyAccess>node.parent).right === node;
return node && node.parent && node.parent.kind === SyntaxKind.PropertyAccess && (<PropertyAccess>node.parent).right === node;
}
function isCallExpressionTarget(node: Node): boolean {
if (isRightSideOfPropertyAccess(node)) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).func === node;
return node && node.parent && node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).func === node;
}
function isNewExpressionTarget(node: Node): boolean {
if (isRightSideOfPropertyAccess(node)) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).func === node;
return node && node.parent && node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).func === node;
}
function isNameOfModuleDeclaration(node: Node) {
@@ -2014,6 +1997,37 @@ module ts {
(node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node));
}
/** Returns true if the position is within a comment */
function isInsideComment(sourceFile: SourceFile, token: Node, position: number): boolean {
// The position has to be: 1. in the leading trivia (before token.getStart()), and 2. within a comment
return position <= token.getStart(sourceFile) &&
(isInsideCommentRange(getTrailingCommentRanges(sourceFile.text, token.getFullStart())) ||
isInsideCommentRange(getLeadingCommentRanges(sourceFile.text, token.getFullStart())));
function isInsideCommentRange(comments: CommentRange[]): boolean {
return forEach(comments, comment => {
// either we are 1. completely inside the comment, or 2. at the end of the comment
if (comment.pos < position && position < comment.end) {
return true;
}
else if (position === comment.end) {
var text = sourceFile.text;
var width = comment.end - comment.pos;
// is single line comment or just /*
if (width <= 2 || text.charCodeAt(comment.pos + 1) === CharacterCodes.slash) {
return true;
}
else {
// is unterminated multi-line comment
return !(text.charCodeAt(comment.end - 1) === CharacterCodes.slash &&
text.charCodeAt(comment.end - 2) === CharacterCodes.asterisk);
}
}
return false;
});
}
}
enum SemanticMeaning {
None = 0x0,
Value = 0x1,
@@ -2317,6 +2331,135 @@ module ts {
}
function getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) {
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
var sourceFile = getSourceFile(filename);
var currentToken = getTokenAtPosition(sourceFile, position);
// Completion not allowed inside comments, bail out if this is the case
if (isInsideComment(sourceFile, currentToken, position)) {
host.log("Returning an empty list because completion was inside a comment.");
return undefined;
}
// The decision to provide completion depends on the previous token, so find it
// Note: previousToken can be undefined if we are the beginning of the file
var previousToken = findPrecedingToken(position, sourceFile);
// 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 to the previous token
if (previousToken && position <= previousToken.end && previousToken.kind === SyntaxKind.Identifier) {
previousToken = findPrecedingToken(previousToken.pos, sourceFile);
}
// Check if this is a valid completion location
if (previousToken && isCompletionListBlocker(previousToken)) {
host.log("Returning an empty list because completion was requested in an invalid position.");
return undefined;
}
// Find the node where completion is requested on, in the case of a completion after a dot, it is the member access expression
// other wise, it is a request for all visible symbols in the scope, and the node is the current location
var node: Node;
var isRightOfDot: boolean;
if (previousToken && previousToken.kind === SyntaxKind.DotToken &&
(previousToken.parent.kind === SyntaxKind.PropertyAccess || previousToken.parent.kind === SyntaxKind.QualifiedName)) {
node = (<PropertyAccess>previousToken.parent).left;
isRightOfDot = true;
}
else {
node = currentToken;
isRightOfDot = false;
}
// Clear the current activeCompletionSession for this session
activeCompletionSession = {
filename: filename,
position: position,
entries: [],
symbols: {},
typeChecker: typeInfoResolver
};
// Populate the completion list
if (isRightOfDot) {
// Right of dot member completion list
var symbols: Symbol[] = [];
isMemberCompletion = true;
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccess) {
var symbol = typeInfoResolver.getSymbolInfo(node);
// This is an alias, follow what it aliases
if (symbol && symbol.flags & SymbolFlags.Import) {
symbol = typeInfoResolver.getAliasedSymbol(symbol);
}
if (symbol && symbol.flags & SymbolFlags.HasExports) {
// Extract module or enum members
forEachValue(symbol.exports, symbol => {
if (typeInfoResolver.isValidPropertyAccess(<PropertyAccess>(node.parent), symbol.name)) {
symbols.push(symbol);
}
});
}
}
var type = typeInfoResolver.getTypeOfNode(node);
if (type) {
// Filter private properties
forEach(type.getApparentProperties(), symbol => {
if (typeInfoResolver.isValidPropertyAccess(<PropertyAccess>(node.parent), symbol.name)) {
symbols.push(symbol);
}
});
}
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
}
else {
var containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(previousToken);
if (containingObjectLiteral) {
// Object literal expression, look up possible property names from contextual type
isMemberCompletion = true;
var contextualType = typeInfoResolver.getContextualType(containingObjectLiteral);
if (!contextualType) {
return undefined;
}
var contextualTypeMembers = typeInfoResolver.getPropertiesOfType(contextualType);
if (contextualTypeMembers && contextualTypeMembers.length > 0) {
// Add filtered items to the completion list
var filteredMembers = filterContextualMembersList(contextualTypeMembers, containingObjectLiteral.properties);
getCompletionEntriesFromSymbols(filteredMembers, activeCompletionSession);
}
}
else {
// Get scope members
isMemberCompletion = false;
/// TODO filter meaning based on the current context
var symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Import;
var symbols = typeInfoResolver.getSymbolsInScope(node, symbolMeanings);
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
}
}
// Add keywords if this is not a member completion list
if (!isMemberCompletion) {
Array.prototype.push.apply(activeCompletionSession.entries, keywordCompletions);
}
return {
isMemberCompletion: isMemberCompletion,
entries: activeCompletionSession.entries
};
function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void {
forEach(symbols, symbol => {
var entry = createCompletionEntry(symbol, session.typeChecker);
@@ -2327,40 +2470,47 @@ module ts {
});
}
function isCompletionListBlocker(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
// We shouldn't be getting a position that is outside the file because
// isEntirelyInsideComment can't handle when the position is out of bounds,
// callers should be fixed, however we should be resilient to bad inputs
// so we return true (this position is a blocker for getting completions)
if (position < 0 || position > TypeScript.fullWidth(sourceUnit)) {
return true;
}
// This method uses Fidelity completely. Some information can be reached using the AST, but not everything.
return TypeScript.Syntax.isEntirelyInsideComment(sourceUnit, position) ||
TypeScript.Syntax.isEntirelyInStringOrRegularExpressionLiteral(sourceUnit, position) ||
isIdentifierDefinitionLocation(sourceUnit, position) ||
isRightOfIllegalDot(sourceUnit, position);
function isCompletionListBlocker(previousToken: Node): boolean {
return isInStringOrRegularExpressionLiteral(previousToken) ||
isIdentifierDefinitionLocation(previousToken) ||
isRightOfIllegalDot(previousToken);
}
function getContainingObjectLiteralApplicableForCompletion(sourceUnit: TypeScript.SourceUnitSyntax, position: number): TypeScript.ISyntaxElement {
function isInStringOrRegularExpressionLiteral(previousToken: Node): boolean {
if (previousToken.kind === SyntaxKind.StringLiteral) {
// The position has to be either: 1. entirely within the token text, or
// 2. at the end position, and the string literal is not terminated
var start = previousToken.getStart();
var end = previousToken.getEnd();
if (start < position && position < end) {
return true;
}
else if (position === end) {
var width = end - start;
var text = previousToken.getSourceFile().text;
return width <= 1 ||
text.charCodeAt(start) !== text.charCodeAt(end - 1) ||
text.charCodeAt(end - 2) === CharacterCodes.backslash;
}
}
else if (previousToken.kind === SyntaxKind.RegularExpressionLiteral) {
return previousToken.getStart() < position && position < previousToken.getEnd();
}
return false;
}
function getContainingObjectLiteralApplicableForCompletion(previousToken: Node): ObjectLiteral {
// The locations in an object literal expression that are applicable for completion are property name definition locations.
var previousToken = getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);
if (previousToken) {
var parent = previousToken.parent;
switch (previousToken.kind()) {
case TypeScript.SyntaxKind.OpenBraceToken: // var x = { |
case TypeScript.SyntaxKind.CommaToken: // var x = { a: 0, |
if (parent && parent.kind() === TypeScript.SyntaxKind.SeparatedList) {
parent = parent.parent;
switch (previousToken.kind) {
case SyntaxKind.OpenBraceToken: // var x = { |
case SyntaxKind.CommaToken: // var x = { a: 0, |
if (parent && parent.kind === SyntaxKind.ObjectLiteral) {
return <ObjectLiteral>parent;
}
if (parent && parent.kind() === TypeScript.SyntaxKind.ObjectLiteralExpression) {
return parent;
}
break;
}
}
@@ -2368,47 +2518,71 @@ module ts {
return undefined;
}
function isIdentifierDefinitionLocation(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
var positionedToken = getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);
function isFunction(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
return true;
}
return false;
}
if (positionedToken) {
var containingNodeKind = TypeScript.Syntax.containingNode(positionedToken) && TypeScript.Syntax.containingNode(positionedToken).kind();
switch (positionedToken.kind()) {
case TypeScript.SyntaxKind.CommaToken:
return containingNodeKind === TypeScript.SyntaxKind.ParameterList ||
containingNodeKind === TypeScript.SyntaxKind.VariableDeclaration ||
containingNodeKind === TypeScript.SyntaxKind.EnumDeclaration; // enum { foo, |
function isIdentifierDefinitionLocation(previousToken: Node): boolean {
if (previousToken) {
var containingNodeKind = previousToken.parent.kind;
switch (previousToken.kind) {
case SyntaxKind.CommaToken:
return containingNodeKind === SyntaxKind.VariableDeclaration ||
containingNodeKind === SyntaxKind.VariableStatement ||
containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { foo, |
isFunction(containingNodeKind);
case TypeScript.SyntaxKind.OpenParenToken:
return containingNodeKind === TypeScript.SyntaxKind.ParameterList ||
containingNodeKind === TypeScript.SyntaxKind.CatchClause;
case SyntaxKind.OpenParenToken:
return containingNodeKind === SyntaxKind.CatchBlock ||
isFunction(containingNodeKind);
case TypeScript.SyntaxKind.OpenBraceToken:
return containingNodeKind === TypeScript.SyntaxKind.EnumDeclaration; // enum { |
case SyntaxKind.OpenBraceToken:
return containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { |
containingNodeKind === SyntaxKind.InterfaceDeclaration; // interface a { |
case TypeScript.SyntaxKind.PublicKeyword:
case TypeScript.SyntaxKind.PrivateKeyword:
case TypeScript.SyntaxKind.StaticKeyword:
case TypeScript.SyntaxKind.DotDotDotToken:
return containingNodeKind === TypeScript.SyntaxKind.Parameter;
case SyntaxKind.SemicolonToken:
return containingNodeKind === SyntaxKind.Property &&
previousToken.parent.parent.kind === SyntaxKind.InterfaceDeclaration; // interface a { f; |
case TypeScript.SyntaxKind.ClassKeyword:
case TypeScript.SyntaxKind.ModuleKeyword:
case TypeScript.SyntaxKind.EnumKeyword:
case TypeScript.SyntaxKind.InterfaceKeyword:
case TypeScript.SyntaxKind.FunctionKeyword:
case TypeScript.SyntaxKind.VarKeyword:
case TypeScript.SyntaxKind.GetKeyword:
case TypeScript.SyntaxKind.SetKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.DotDotDotToken:
return containingNodeKind === SyntaxKind.Parameter;
case SyntaxKind.ClassKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.FunctionKeyword:
case SyntaxKind.VarKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.SetKeyword:
return true;
}
// Previous token may have been a keyword that was converted to an identifier.
switch (positionedToken.text()) {
switch (previousToken.getText()) {
case "class":
case "interface":
case "enum":
case "module":
case "function":
case "var":
// TODO: add let and const
return true;
}
}
@@ -2416,44 +2590,15 @@ module ts {
return false;
}
function getNonIdentifierCompleteTokenOnLeft(sourceUnit: TypeScript.SourceUnitSyntax, position: number): TypeScript.ISyntaxToken {
var positionedToken = TypeScript.Syntax.findCompleteTokenOnLeft(sourceUnit, position, /*includeSkippedTokens*/true);
if (positionedToken && position === TypeScript.end(positionedToken) && positionedToken.kind() == TypeScript.SyntaxKind.EndOfFileToken) {
// EndOfFile token is not interesting, get the one before it
positionedToken = TypeScript. previousToken(positionedToken, /*includeSkippedTokens*/true);
}
if (positionedToken && position === TypeScript.end(positionedToken) && positionedToken.kind() === TypeScript.SyntaxKind.IdentifierName) {
// The caret is at the end of an identifier, the decision to provide completion depends on the previous token
positionedToken = TypeScript.previousToken(positionedToken, /*includeSkippedTokens*/true);
}
return positionedToken;
}
function isRightOfIllegalDot(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
var positionedToken = getNonIdentifierCompleteTokenOnLeft(sourceUnit, position);
if (positionedToken) {
switch (positionedToken.kind()) {
case TypeScript.SyntaxKind.DotToken:
var leftOfDotPositionedToken = TypeScript.previousToken(positionedToken, /*includeSkippedTokens*/true);
return leftOfDotPositionedToken && leftOfDotPositionedToken.kind() === TypeScript.SyntaxKind.NumericLiteral;
case TypeScript.SyntaxKind.NumericLiteral:
var text = positionedToken.text();
return text.charAt(text.length - 1) === ".";
}
function isRightOfIllegalDot(previousToken: Node): boolean {
if (previousToken && previousToken.kind === SyntaxKind.NumericLiteral) {
var text = previousToken.getFullText();
return text.charAt(text.length - 1) === ".";
}
return false;
}
function isPunctuation(kind: SyntaxKind) {
return (SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation);
}
function filterContextualMembersList(contextualMemberSymbols: Symbol[], existingMembers: Declaration[]): Symbol[] {
if (!existingMembers || existingMembers.length === 0) {
return contextualMemberSymbols;
@@ -2483,162 +2628,6 @@ module ts {
return filteredMembers;
}
synchronizeHostData();
filename = TypeScript.switchToForwardSlashes(filename);
var sourceFile = getSourceFile(filename);
var sourceUnit = sourceFile.getSourceUnit();
if (isCompletionListBlocker(sourceFile.getSyntaxTree().sourceUnit(), position)) {
host.log("Returning an empty list because completion was blocked.");
return null;
}
var node = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position, /*useTrailingTriviaAsLimChar*/ true, /*forceInclusive*/ true);
if (node && node.kind() === TypeScript.SyntaxKind.IdentifierName &&
TypeScript.start(node) === TypeScript.end(node)) {
// Ignore missing name nodes
node = node.parent;
}
var isRightOfDot = false;
if (node &&
node.kind() === TypeScript.SyntaxKind.MemberAccessExpression &&
TypeScript.end((<TypeScript.MemberAccessExpressionSyntax>node).expression) < position) {
isRightOfDot = true;
node = (<TypeScript.MemberAccessExpressionSyntax>node).expression;
}
else if (node &&
node.kind() === TypeScript.SyntaxKind.QualifiedName &&
TypeScript.end((<TypeScript.QualifiedNameSyntax>node).left) < position) {
isRightOfDot = true;
node = (<TypeScript.QualifiedNameSyntax>node).left;
}
else if (node && node.parent &&
node.kind() === TypeScript.SyntaxKind.IdentifierName &&
node.parent.kind() === TypeScript.SyntaxKind.MemberAccessExpression &&
(<TypeScript.MemberAccessExpressionSyntax>node.parent).name === node) {
isRightOfDot = true;
node = (<TypeScript.MemberAccessExpressionSyntax>node.parent).expression;
}
else if (node && node.parent &&
node.kind() === TypeScript.SyntaxKind.IdentifierName &&
node.parent.kind() === TypeScript.SyntaxKind.QualifiedName &&
(<TypeScript.QualifiedNameSyntax>node.parent).right === node) {
isRightOfDot = true;
node = (<TypeScript.QualifiedNameSyntax>node.parent).left;
}
// TODO: this is a hack for now, we need a proper walking mechanism to verify that we have the correct node
var precedingToken = findTokenOnLeftOfPosition(sourceFile, TypeScript.end(node));
var mappedNode: Node;
if (!precedingToken) {
mappedNode = sourceFile;
}
else if (isPunctuation(precedingToken.kind)) {
mappedNode = precedingToken.parent;
}
else {
mappedNode = precedingToken;
}
Debug.assert(mappedNode, "Could not map a Fidelity node to an AST node");
// Get the completions
activeCompletionSession = {
filename: filename,
position: position,
entries: [],
symbols: {},
location: mappedNode,
typeChecker: typeInfoResolver
};
// Right of dot member completion list
if (isRightOfDot) {
var symbols: Symbol[] = [];
isMemberCompletion = true;
if (mappedNode.kind === SyntaxKind.Identifier || mappedNode.kind === SyntaxKind.QualifiedName || mappedNode.kind === SyntaxKind.PropertyAccess) {
var symbol = typeInfoResolver.getSymbolInfo(mappedNode);
// This is an alias, follow what it aliases
if (symbol && symbol.flags & SymbolFlags.Import) {
symbol = typeInfoResolver.getAliasedSymbol(symbol);
}
if (symbol && symbol.flags & SymbolFlags.HasExports) {
// Extract module or enum members
forEachValue(symbol.exports, symbol => {
if (typeInfoResolver.isValidPropertyAccess(<PropertyAccess>(mappedNode.parent), symbol.name)) {
symbols.push(symbol);
}
});
}
}
var type = typeInfoResolver.getTypeOfNode(mappedNode);
if (type) {
// Filter private properties
forEach(type.getApparentProperties(), symbol => {
if (typeInfoResolver.isValidPropertyAccess(<PropertyAccess>(mappedNode.parent), symbol.name)) {
symbols.push(symbol);
}
});
}
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
}
else {
var containingObjectLiteral = getContainingObjectLiteralApplicableForCompletion(sourceFile.getSyntaxTree().sourceUnit(), position);
// Object literal expression, look up possible property names from contextual type
if (containingObjectLiteral) {
var objectLiteral = <ObjectLiteral>(mappedNode.kind === SyntaxKind.ObjectLiteral ? mappedNode : getAncestor(mappedNode, SyntaxKind.ObjectLiteral));
Debug.assert(objectLiteral);
isMemberCompletion = true;
var contextualType = typeInfoResolver.getContextualType(objectLiteral);
if (!contextualType) {
return undefined;
}
var contextualTypeMembers = typeInfoResolver.getPropertiesOfType(contextualType);
if (contextualTypeMembers && contextualTypeMembers.length > 0) {
// Add filtered items to the completion list
var filteredMembers = filterContextualMembersList(contextualTypeMembers, objectLiteral.properties);
getCompletionEntriesFromSymbols(filteredMembers, activeCompletionSession);
}
}
// Get scope members
else {
isMemberCompletion = false;
/// TODO filter meaning based on the current context
var symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Import;
var symbols = typeInfoResolver.getSymbolsInScope(mappedNode, symbolMeanings);
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
}
}
// Add keywords if this is not a member completion list
if (!isMemberCompletion) {
Array.prototype.push.apply(activeCompletionSession.entries, keywordCompletions);
}
return {
isMemberCompletion: isMemberCompletion,
entries: activeCompletionSession.entries
};
}
function getCompletionEntryDetails(filename: string, position: number, entryName: string): CompletionEntryDetails {
@@ -2646,6 +2635,8 @@ module ts {
// in the getCompletionsAtPosition earlier
filename = TypeScript.switchToForwardSlashes(filename);
var sourceFile = getSourceFile(filename);
var session = activeCompletionSession;
// Ensure that the current active completion session is still valid for this request
@@ -2662,7 +2653,8 @@ module ts {
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), session.location, session.typeChecker, session.location, SemanticMeaning.All);
var location = getTouchingPropertyName(sourceFile, position);
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), location, session.typeChecker, location, SemanticMeaning.All);
return {
name: entryName,
kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
@@ -2711,6 +2703,7 @@ module ts {
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement;
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
@@ -2782,6 +2775,7 @@ module ts {
case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement;
case SyntaxKind.ClassDeclaration: return ScriptElementKind.classElement;
case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement;
case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement;
case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement;
case SyntaxKind.VariableDeclaration: return node.flags & NodeFlags.Const ? ScriptElementKind.constantElement: ScriptElementKind.variableElement;
case SyntaxKind.FunctionDeclaration: return ScriptElementKind.functionElement;
@@ -2796,8 +2790,8 @@ module ts {
case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement;
case SyntaxKind.EnumMember: return ScriptElementKind.variableElement;
case SyntaxKind.Parameter: return (node.flags & NodeFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
return ScriptElementKind.unknown;
}
return ScriptElementKind.unknown;
}
function getSymbolModifiers(symbol: Symbol): string {
@@ -2824,14 +2818,24 @@ module ts {
var type = typeResolver.getTypeOfSymbol(symbol);
if (type) {
if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
// try get the call/construct signature from the type if it matches
var callExpression: CallExpression;
if (location.parent.kind === SyntaxKind.PropertyAccess && (<PropertyAccess>location.parent).right === location) {
if (location.parent && location.parent.kind === SyntaxKind.PropertyAccess) {
var right = (<PropertyAccess>location.parent).right;
// 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.kind === SyntaxKind.Missing)){
location = location.parent;
}
callExpression = <CallExpression>location.parent;
}
// try get the call/construct signature from the type if it matches
var callExpression: CallExpression;
if (location.kind === SyntaxKind.CallExpression || location.kind === SyntaxKind.NewExpression) {
callExpression = <CallExpression> location;
}
else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
callExpression = <CallExpression>location.parent;
}
if (callExpression) {
var candidateSignatures: Signature[] = [];
signature = typeResolver.getResolvedSignature(callExpression, candidateSignatures);
if (!signature && candidateSignatures.length) {
@@ -2936,6 +2940,16 @@ module ts {
addFullSymbolName(symbol);
writeTypeParametersOfSymbol(symbol, sourceFile);
}
if (symbolFlags & SymbolFlags.TypeAlias) {
addNewLineIfDisplayPartsExist();
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
displayParts.push(spacePart());
addFullSymbolName(symbol);
displayParts.push(spacePart());
displayParts.push(punctuationPart(SyntaxKind.EqualsToken));
displayParts.push(spacePart());
displayParts.push.apply(displayParts, typeToDisplayParts(typeResolver, typeResolver.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
}
if (symbolFlags & SymbolFlags.Enum) {
addNewLineIfDisplayPartsExist();
displayParts.push(keywordPart(SyntaxKind.EnumKeyword));
@@ -4523,6 +4537,7 @@ module ts {
case SyntaxKind.TypeParameter:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.TypeLiteral:
return SemanticMeaning.Type;
@@ -4569,11 +4584,10 @@ module ts {
return root.parent.kind === SyntaxKind.TypeReference && !isLastClause;
}
function isInRightSideOfImport(node: EntityName) {
function isInRightSideOfImport(node: Node) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).entityName === node;
}
@@ -5027,10 +5041,17 @@ module ts {
function getIndentationAtPosition(filename: string, position: number, editorOptions: EditorOptions) {
filename = TypeScript.switchToForwardSlashes(filename);
var start = new Date().getTime();
var sourceFile = getCurrentSourceFile(filename);
host.log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start));
var start = new Date().getTime();
var options = new TypeScript.FormattingOptions(!editorOptions.ConvertTabsToSpaces, editorOptions.TabSize, editorOptions.IndentSize, editorOptions.NewLineCharacter)
return formatting.SmartIndenter.getIndentation(position, sourceFile, options);
var result = formatting.SmartIndenter.getIndentation(position, sourceFile, options);
host.log("getIndentationAtPosition: computeIndentation : " + (new Date().getTime() - start));
return result;
}
function getFormattingManager(filename: string, options: FormatCodeOptions) {
@@ -5132,16 +5153,7 @@ module ts {
// OK, we have found a match in the file. This is only an acceptable match if
// it is contained within a comment.
var token = getTokenAtPosition(sourceFile, matchPosition);
if (token.getStart() <= matchPosition && matchPosition < token.getEnd()) {
// match was within the token itself. Not in the comment. Keep searching
// descriptor.
continue;
}
// Looks to be within the trivia. See if we can find the comment containing it.
if (!getContainingComment(getTrailingCommentRanges(fileContents, token.getFullStart()), matchPosition) &&
!getContainingComment(getLeadingCommentRanges(fileContents, token.getFullStart()), matchPosition)) {
if (!isInsideComment(sourceFile, token, matchPosition)) {
continue;
}
+6 -6
View File
@@ -226,12 +226,12 @@ module ts.SignatureHelp {
};
}
if (node.kind === SyntaxKind.GreaterThanToken
|| node.kind === SyntaxKind.CloseParenToken
|| node === parent.func) {
return undefined;
}
// findListItemInfo can return undefined if we are not in parent's argument list
// or type argument list. This includes cases where the cursor is:
// - To the right of the closing paren
// - Between the type arguments and the arguments (greater than token)
// - On the target of the call (parent.func)
// - On the 'new' keyword in a 'new' expression
return findListItemInfo(node);
}
+13 -10
View File
@@ -7,6 +7,15 @@ module ts {
export function findListItemInfo(node: Node): ListItemInfo {
var syntaxList = findContainingList(node);
// It is possible at this point for syntaxList to be undefined, either if
// node.parent had no list child, or if none of its list children contained
// the span of node. If this happens, return undefined. The caller should
// handle this case.
if (!syntaxList) {
return undefined;
}
var children = syntaxList.getChildren();
var index = indexOf(children, node);
@@ -32,13 +41,6 @@ module ts {
}
});
// syntaxList should not be undefined here. If it is, there is a problem. Find out if
// there at least is a child that is a list.
if (!syntaxList) {
Debug.assert(findChildOfKind(node.parent, SyntaxKind.SyntaxList),
"Node of kind " + SyntaxKind[node.parent.kind] + " has no list children");
}
return syntaxList;
}
@@ -95,11 +97,12 @@ module ts {
var child = current.getChildAt(i);
var start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
if (start <= position) {
if (position < child.getEnd()) {
var end = child.getEnd();
if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
current = child;
continue outer;
}
else if (includeItemAtEndPosition && child.getEnd() === position) {
else if (includeItemAtEndPosition && end === position) {
var previousToken = findPrecedingToken(position, sourceFile, child);
if (previousToken && includeItemAtEndPosition(previousToken)) {
return previousToken;
@@ -180,7 +183,7 @@ module ts {
for (var i = 0, len = children.length; i < len; ++i) {
var child = children[i];
if (nodeHasTokens(child)) {
if (position < child.end) {
if (position <= child.end) {
if (child.getStart(sourceFile) >= position) {
// actual start of the node is past the position - previous token should be at the end of previous child
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);