Merge remote-tracking branch 'origin/master' into

serverConfigurationMessage.
This commit is contained in:
steveluc
2015-03-17 17:51:16 -07:00
485 changed files with 9597 additions and 2722 deletions
+8 -7
View File
@@ -322,13 +322,14 @@ module ts {
}
else {
bindDeclaration(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes, /*isBlockScopeContainer*/ true);
if (state === ModuleInstanceState.ConstEnumOnly) {
// mark value module as module that contains only enums
node.symbol.constEnumOnlyModule = true;
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
if (node.symbol.constEnumOnlyModule === undefined) {
// non-merged case - use the current state
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
}
else if (node.symbol.constEnumOnlyModule) {
// const only value module was merged with instantiated module - reset flag
node.symbol.constEnumOnlyModule = false;
else {
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
}
}
}
@@ -505,7 +506,7 @@ module ts {
bindChildren(node, 0, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.ExportAssignment:
if ((<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
if ((<ExportAssignment>node).expression && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier) {
// An export default clause with an identifier exports all meanings of that identifier
declareSymbol(container.symbol.exports, container.symbol, <Declaration>node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
}
+138 -72
View File
@@ -79,8 +79,7 @@ module ts {
let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let inferenceFailureType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, false, false);
let unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, false, false);
@@ -567,7 +566,7 @@ module ts {
}
function getTargetOfExportAssignment(node: ExportAssignment): Symbol {
return resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
return node.expression && resolveEntityName(<Identifier>node.expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
}
function getTargetOfImportDeclaration(node: Declaration): Symbol {
@@ -623,7 +622,7 @@ module ts {
if (!links.referenced) {
links.referenced = true;
let node = getDeclarationOfAliasSymbol(symbol);
if (node.kind === SyntaxKind.ExportAssignment) {
if (node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression) {
// export default <symbol>
checkExpressionCached((<ExportAssignment>node).expression);
}
@@ -784,7 +783,7 @@ module ts {
}
function getExportsForModule(moduleSymbol: Symbol): SymbolTable {
if (compilerOptions.target < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES6) {
// A default export hides all other exports in CommonJS and AMD modules
let defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
if (defaultSymbol) {
@@ -1813,6 +1812,11 @@ module ts {
case SyntaxKind.ParenthesizedType:
return isDeclarationVisible(<Declaration>node.parent);
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
case SyntaxKind.ImportSpecifier:
return false;
// Type parameters are always visible
case SyntaxKind.TypeParameter:
// Source file is always visible
@@ -2073,7 +2077,16 @@ module ts {
}
// Handle export default expressions
if (declaration.kind === SyntaxKind.ExportAssignment) {
return links.type = checkExpression((<ExportAssignment>declaration).expression);
var exportAssignment = <ExportAssignment>declaration;
if (exportAssignment.expression) {
return links.type = checkExpression(exportAssignment.expression);
}
else if (exportAssignment.type) {
return links.type = getTypeFromTypeNode(exportAssignment.type);
}
else {
return links.type = anyType;
}
}
// Handle variable, parameter or property
links.type = resolvingType;
@@ -3505,6 +3518,7 @@ module ts {
return t => {
for (let i = 0; i < context.typeParameters.length; i++) {
if (t === context.typeParameters[i]) {
context.inferences[i].isFixed = true;
return getInferredType(context, i);
}
}
@@ -4363,8 +4377,11 @@ module ts {
}
function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void {
// The downfallType/bestSupertypeDownfallType is the first type that caused a particular candidate
// to not be the common supertype. So if it weren't for this one downfallType (and possibly others),
// the type in question could have been the common supertype.
let bestSupertype: Type;
let bestSupertypeDownfallType: Type; // The type that caused bestSupertype not to be the common supertype
let bestSupertypeDownfallType: Type;
let bestSupertypeScore = 0;
for (let i = 0; i < types.length; i++) {
@@ -4379,6 +4396,8 @@ module ts {
}
}
Debug.assert(!!downfallType, "If there is no common supertype, each type should have a downfallType");
if (score > bestSupertypeScore) {
bestSupertype = types[i];
bestSupertypeDownfallType = downfallType;
@@ -4561,13 +4580,12 @@ module ts {
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
let inferences: TypeInferences[] = [];
for (let unused of typeParameters) {
inferences.push({ primary: undefined, secondary: undefined });
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
}
return {
typeParameters: typeParameters,
inferUnionTypes: inferUnionTypes,
inferenceCount: 0,
inferences: inferences,
typeParameters,
inferUnionTypes,
inferences,
inferredTypes: new Array(typeParameters.length),
};
}
@@ -4613,11 +4631,21 @@ module ts {
for (let i = 0; i < typeParameters.length; i++) {
if (target === typeParameters[i]) {
let inferences = context.inferences[i];
let candidates = inferiority ?
inferences.secondary || (inferences.secondary = []) :
inferences.primary || (inferences.primary = []);
if (!contains(candidates, source)) candidates.push(source);
break;
if (!inferences.isFixed) {
// Any inferences that are made to a type parameter in a union type are inferior
// to inferences made to a flat (non-union) type. This is because if we infer to
// T | string[], we really don't know if we should be inferring to T or not (because
// the correct constituent on the target side could be string[]). Therefore, we put
// such inferior inferences into a secondary bucket, and only use them if the primary
// bucket is empty.
let candidates = inferiority ?
inferences.secondary || (inferences.secondary = []) :
inferences.primary || (inferences.primary = []);
if (!contains(candidates, source)) {
candidates.push(source);
}
}
return;
}
}
}
@@ -4723,21 +4751,35 @@ module ts {
function getInferredType(context: InferenceContext, index: number): Type {
let inferredType = context.inferredTypes[index];
let inferenceSucceeded: boolean;
if (!inferredType) {
let inferences = getInferenceCandidates(context, index);
if (inferences.length) {
// Infer widened union or supertype, or the undefined type for no common supertype
// Infer widened union or supertype, or the unknown type for no common supertype
let unionOrSuperType = context.inferUnionTypes ? getUnionType(inferences) : getCommonSupertype(inferences);
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : inferenceFailureType;
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
inferenceSucceeded = !!unionOrSuperType;
}
else {
// Infer the empty object type when no inferences were made
// Infer the empty object type when no inferences were made. It is important to remember that
// in this case, inference still succeeds, meaning there is no error for not having inference
// candidates. An inference error only occurs when there are *conflicting* candidates, i.e.
// candidates with no common supertype.
inferredType = emptyObjectType;
inferenceSucceeded = true;
}
if (inferredType !== inferenceFailureType) {
// Only do the constraint check if inference succeeded (to prevent cascading errors)
if (inferenceSucceeded) {
let constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
inferredType = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
}
else if (context.failedTypeParameterIndex === undefined || context.failedTypeParameterIndex > index) {
// If inference failed, it is necessary to record the index of the failed type parameter (the one we are on).
// It might be that inference has already failed on a later type parameter on a previous call to inferTypeArguments.
// So if this failure is on preceding type parameter, this type parameter is the new failure index.
context.failedTypeParameterIndex = index;
}
context.inferredTypes[index] = inferredType;
}
return inferredType;
@@ -6334,11 +6376,32 @@ module ts {
return getSignatureInstantiation(signature, getInferredTypes(context));
}
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[]): InferenceContext {
function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument: boolean[], context: InferenceContext): void {
let typeParameters = signature.typeParameters;
let context = createInferenceContext(typeParameters, /*inferUnionTypes*/ false);
let inferenceMapper = createInferenceMapper(context);
// Clear out all the inference results from the last time inferTypeArguments was called on this context
for (let i = 0; i < typeParameters.length; i++) {
// As an optimization, we don't have to clear (and later recompute) inferred types
// for type parameters that have already been fixed on the previous call to inferTypeArguments.
// It would be just as correct to reset all of them. But then we'd be repeating the same work
// for the type parameters that were fixed, namely the work done by getInferredType.
if (!context.inferences[i].isFixed) {
context.inferredTypes[i] = undefined;
}
}
// On this call to inferTypeArguments, we may get more inferences for certain type parameters that were not
// fixed last time. This means that a type parameter that failed inference last time may succeed this time,
// or vice versa. Therefore, the failedTypeParameterIndex is useless if it points to an unfixed type parameter,
// because it may change. So here we reset it. However, getInferredType will not revisit any type parameters
// that were previously fixed. So if a fixed type parameter failed previously, it will fail again because
// it will contain the exact same set of inferences. So if we reset the index from a fixed type parameter,
// we will lose information that we won't recover this time around.
if (context.failedTypeParameterIndex !== undefined && !context.inferences[context.failedTypeParameterIndex].isFixed) {
context.failedTypeParameterIndex = undefined;
}
// We perform two passes over the arguments. In the first pass we infer from all arguments, but use
// wildcards for all context sensitive function expressions.
for (let i = 0; i < args.length; i++) {
@@ -6373,18 +6436,7 @@ module ts {
}
}
let inferredTypes = getInferredTypes(context);
// Inference has failed if the inferenceFailureType type is in list of inferences
context.failedTypeParameterIndex = indexOf(inferredTypes, inferenceFailureType);
// Wipe out the inferenceFailureType from the array so that error recovery can work properly
for (let i = 0; i < inferredTypes.length; i++) {
if (inferredTypes[i] === inferenceFailureType) {
inferredTypes[i] = unknownType;
}
}
return context;
getInferredTypes(context);
}
function checkTypeArguments(signature: Signature, typeArguments: TypeNode[], typeArgumentResultTypes: Type[], reportErrors: boolean): boolean {
@@ -6618,15 +6670,17 @@ module ts {
return resolveErrorCall(node);
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
for (let current of candidates) {
if (!hasCorrectArity(node, args, current)) {
for (let originalCandidate of candidates) {
if (!hasCorrectArity(node, args, originalCandidate)) {
continue;
}
let originalCandidate = current;
let inferenceResult: InferenceContext;
let candidate: Signature;
let typeArgumentsAreValid: boolean;
let inferenceContext = originalCandidate.typeParameters
? createInferenceContext(originalCandidate.typeParameters, /*inferUnionTypes*/ false)
: undefined;
while (true) {
candidate = originalCandidate;
if (candidate.typeParameters) {
@@ -6636,9 +6690,9 @@ module ts {
typeArgumentsAreValid = checkTypeArguments(candidate, typeArguments, typeArgumentTypes, /*reportErrors*/ false)
}
else {
inferenceResult = inferTypeArguments(candidate, args, excludeArgument);
typeArgumentsAreValid = inferenceResult.failedTypeParameterIndex < 0;
typeArgumentTypes = inferenceResult.inferredTypes;
inferTypeArguments(candidate, args, excludeArgument, inferenceContext);
typeArgumentsAreValid = inferenceContext.failedTypeParameterIndex === undefined;
typeArgumentTypes = inferenceContext.inferredTypes;
}
if (!typeArgumentsAreValid) {
break;
@@ -6668,7 +6722,7 @@ module ts {
else {
candidateForTypeArgumentError = originalCandidate;
if (!typeArguments) {
resultOfFailedInference = inferenceResult;
resultOfFailedInference = inferenceContext;
}
}
}
@@ -10044,6 +10098,12 @@ module ts {
}
}
}
else {
if (languageVersion >= ScriptTarget.ES6) {
// Import equals declaration is deprecated in es6 or above
grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead);
}
}
}
}
@@ -10075,13 +10135,27 @@ module ts {
if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
}
if (node.expression.kind === SyntaxKind.Identifier) {
markExportAsReferenced(node);
if (node.expression) {
if (node.expression.kind === SyntaxKind.Identifier) {
markExportAsReferenced(node);
}
else {
checkExpressionCached(node.expression);
}
}
else {
checkExpressionCached(node.expression);
if (node.type) {
checkSourceElement(node.type);
if (!isInAmbientContext(node)) {
grammarErrorOnFirstToken(node.type, Diagnostics.A_type_annotation_on_an_export_statement_is_only_allowed_in_an_ambient_external_module_declaration);
}
}
checkExternalModuleExports(container);
if (node.isExportEquals && languageVersion >= ScriptTarget.ES6) {
// export assignment is deprecated in es6 or above
grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead);
}
}
function getModuleStatements(node: Declaration): ModuleElement[] {
@@ -10124,7 +10198,7 @@ module ts {
if (!links.exportsChecked) {
let defaultSymbol = getExportAssignmentSymbol(moduleSymbol);
if (defaultSymbol) {
if (hasExportedMembers(moduleSymbol)) {
if (languageVersion < ScriptTarget.ES6 && hasExportedMembers(moduleSymbol)) {
let declaration = getDeclarationOfAliasSymbol(defaultSymbol) || defaultSymbol.valueDeclaration;
error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements);
}
@@ -10914,7 +10988,7 @@ module ts {
}
function generateNameForExportAssignment(node: ExportAssignment) {
if (node.expression.kind !== SyntaxKind.Identifier) {
if (node.expression && node.expression.kind !== SyntaxKind.Identifier) {
assignGeneratedName(node, makeUniqueName("default"));
}
}
@@ -10947,7 +11021,15 @@ module ts {
function getExportNameSubstitution(symbol: Symbol, location: Node): string {
if (isExternalModuleSymbol(symbol.parent)) {
return "exports." + unescapeIdentifier(symbol.name);
var symbolName = unescapeIdentifier(symbol.name);
// If this is es6 or higher, just use the name of the export
// no need to qualify it.
if (languageVersion >= ScriptTarget.ES6) {
return symbolName;
}
else {
return "exports." + symbolName;
}
}
let node = location;
let containerSymbol = getParentOfSymbol(symbol);
@@ -10975,7 +11057,7 @@ module ts {
return getExportNameSubstitution(exportSymbol, node.parent);
}
// Named imports from ES6 import declarations are rewritten
if (symbol.flags & SymbolFlags.Alias) {
if (symbol.flags & SymbolFlags.Alias && languageVersion < ScriptTarget.ES6) {
return getAliasNameSubstitution(symbol);
}
}
@@ -11011,7 +11093,6 @@ module ts {
return true;
}
}
return forEachChild(node, isReferencedAliasDeclaration);
}
function isImplementationOfOverload(node: FunctionLikeDeclaration) {
@@ -11085,26 +11166,11 @@ module ts {
function getBlockScopedVariableId(n: Identifier): number {
Debug.assert(!nodeIsSynthesized(n));
// ignore name parts of property access expressions
if (n.parent.kind === SyntaxKind.PropertyAccessExpression &&
(<PropertyAccessExpression>n.parent).name === n) {
return undefined;
}
let isVariableDeclarationOrBindingElement =
n.parent.kind === SyntaxKind.BindingElement || (n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n);
// ignore property names in object binding patterns
if (n.parent.kind === SyntaxKind.BindingElement &&
(<BindingElement>n.parent).propertyName === n) {
return undefined;
}
// for names in variable declarations and binding elements try to short circuit and fetch symbol from the node
let declarationSymbol: Symbol =
(n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n) ||
n.parent.kind === SyntaxKind.BindingElement
? getSymbolOfNode(n.parent)
: undefined;
let symbol = declarationSymbol ||
let symbol =
(isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) ||
getNodeLinks(n).resolvedSymbol ||
resolveName(n, n.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
@@ -158,6 +158,10 @@ module ts {
An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive: { code: 1198, category: DiagnosticCategory.Error, key: "An extended Unicode escape value must be between 0x0 and 0x10FFFF inclusive." },
Unterminated_Unicode_escape_sequence: { code: 1199, category: DiagnosticCategory.Error, key: "Unterminated Unicode escape sequence." },
Line_terminator_not_permitted_before_arrow: { code: 1200, category: DiagnosticCategory.Error, key: "Line terminator not permitted before arrow." },
A_type_annotation_on_an_export_statement_is_only_allowed_in_an_ambient_external_module_declaration: { code: 1201, category: DiagnosticCategory.Error, key: "A type annotation on an export statement is only allowed in an ambient external module declaration." },
Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile external modules into amd or commonjs when targeting es6 or higher." },
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." },
+18 -1
View File
@@ -617,12 +617,29 @@
},
"Unterminated Unicode escape sequence.": {
"category": "Error",
"code": 1199
"code": 1199
},
"Line terminator not permitted before arrow.": {
"category": "Error",
"code": 1200
},
"A type annotation on an export statement is only allowed in an ambient external module declaration.": {
"category": "Error",
"code": 1201
},
"Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead.": {
"category": "Error",
"code": 1202
},
"Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead.": {
"category": "Error",
"code": 1203
},
"Cannot compile external modules into amd or commonjs when targeting es6 or higher.": {
"category": "Error",
"code": 1204
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
+579 -210
View File
File diff suppressed because it is too large Load Diff
+29 -14
View File
@@ -283,7 +283,8 @@ module ts {
visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
case SyntaxKind.ExportAssignment:
return visitNodes(cbNodes, node.modifiers) ||
visitNode(cbNode, (<ExportAssignment>node).expression);
visitNode(cbNode, (<ExportAssignment>node).expression) ||
visitNode(cbNode, (<ExportAssignment>node).type);
case SyntaxKind.TemplateExpression:
return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNodes, (<TemplateExpression>node).templateSpans);
case SyntaxKind.TemplateSpan:
@@ -613,7 +614,7 @@ module ts {
// change the token touching it, we actually need to look back *at least* one token so
// that the prior token sees that change.
let maxLookahead = 1;
let start = changeRange.span.start;
// the first iteration aligns us with the change start. subsequent iteration move us to
@@ -831,7 +832,7 @@ module ts {
// will immediately bail out of walking any subtrees when we can see that their parents
// are already correct.
let result = parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /* setParentNode */ true)
return result;
}
@@ -1986,7 +1987,7 @@ module ts {
//
// let v = new List < A, B >()
//
// then we have a problem. "v = new List<A" doesn't intersect the change range, so we
// then we have a problem. "v = new List<A" doesn't intersect the change range, so we
// start reparsing at "B" and we completely fail to handle this properly.
//
// In order to prevent this, we do not allow a variable declarator to be reused if it
@@ -3008,9 +3009,9 @@ module ts {
Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction, identifier.pos);
let parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter, identifier.pos);
parameter.name = identifier;
parameter.name = identifier;
finishNode(parameter);
node.parameters = <NodeArray<ParameterDeclaration>>[parameter];
@@ -3140,8 +3141,8 @@ module ts {
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
// Arrow functions are never generators.
//
// Arrow functions are never generators.
//
// If we're speculatively parsing a signature for a parenthesized arrow function, then
// we have to have a complete parameter list. Otherwise we might see something like
// a => (b => c)
@@ -3206,7 +3207,7 @@ module ts {
// Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
// we do not that for the 'whenFalse' part.
let node = <ConditionalExpression>createNode(SyntaxKind.ConditionalExpression, leftOperand.pos);
node.condition = leftOperand;
node.condition = leftOperand;
node.questionToken = questionToken;
node.whenTrue = allowInAnd(parseAssignmentExpressionOrHigher);
node.colonToken = parseExpectedToken(SyntaxKind.ColonToken, /*reportAtCurrentPosition:*/ false,
@@ -4526,7 +4527,13 @@ module ts {
}
function parseClassDeclaration(fullStart: number, modifiers: ModifiersArray): ClassDeclaration {
let node = <ClassDeclaration>createNode(SyntaxKind.ClassDeclaration, fullStart);
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
let savedStrictModeContext = inStrictModeContext();
if (languageVersion >= ScriptTarget.ES6) {
setStrictModeContext(true);
}
var node = <ClassDeclaration>createNode(SyntaxKind.ClassDeclaration, fullStart);
setModifiers(node, modifiers);
parseExpected(SyntaxKind.ClassKeyword);
node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
@@ -4546,7 +4553,10 @@ module ts {
else {
node.members = createMissingList<ClassElement>();
}
return finishNode(node);
var finishedNode = finishNode(node);
setStrictModeContext(savedStrictModeContext);
return finishedNode;
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
@@ -4774,7 +4784,7 @@ module ts {
// walker.
let result = parseExpression();
// Ensure the string being required is in our 'identifier' table. This will ensure
// that features like 'find refs' will look inside this file when search for its name.
// that features like 'find refs' will look inside this file when search for its name.
if (result.kind === SyntaxKind.StringLiteral) {
internIdentifier((<LiteralExpression>result).text);
}
@@ -4867,12 +4877,17 @@ module ts {
setModifiers(node, modifiers);
if (parseOptional(SyntaxKind.EqualsToken)) {
node.isExportEquals = true;
node.expression = parseAssignmentExpressionOrHigher();
}
else {
parseExpected(SyntaxKind.DefaultKeyword);
if (parseOptional(SyntaxKind.ColonToken)) {
node.type = parseType();
}
else {
node.expression = parseAssignmentExpressionOrHigher();
}
}
//node.exportName = parseIdentifier();
node.expression = parseAssignmentExpressionOrHigher();
parseSemicolon();
return finishNode(node);
}
+41 -26
View File
@@ -2,8 +2,10 @@
/// <reference path="emitter.ts" />
module ts {
/* @internal */ export let programTime = 0;
/* @internal */ export let emitTime = 0;
/* @internal */ export let ioReadTime = 0;
/* @internal */ export let ioWriteTime = 0;
/** The version of the TypeScript compiler release */
export let version = "1.5.0.0";
@@ -36,33 +38,34 @@ module ts {
}
text = "";
}
return text !== undefined ? createSourceFile(fileName, text, languageVersion) : undefined;
}
function directoryExists(directoryPath: string): boolean {
if (hasProperty(existingDirectories, directoryPath)) {
return true;
}
if (sys.directoryExists(directoryPath)) {
existingDirectories[directoryPath] = true;
return true;
}
return false;
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
let parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
sys.createDirectory(directoryPath);
}
}
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
function directoryExists(directoryPath: string): boolean {
if (hasProperty(existingDirectories, directoryPath)) {
return true;
}
if (sys.directoryExists(directoryPath)) {
existingDirectories[directoryPath] = true;
return true;
}
return false;
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
let parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
sys.createDirectory(directoryPath);
}
}
try {
var start = new Date().getTime();
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
sys.writeFile(fileName, data, writeByteOrderMark);
ioWriteTime += new Date().getTime() - start;
}
catch (e) {
if (onError) {
@@ -120,16 +123,19 @@ module ts {
let diagnostics = createDiagnosticCollection();
let seenNoDefaultLib = options.noLib;
let commonSourceDirectory: string;
host = host || createCompilerHost(options);
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
let start = new Date().getTime();
host = host || createCompilerHost(options);
forEach(rootNames, name => processRootFile(name, false));
if (!seenNoDefaultLib) {
processRootFile(host.getDefaultLibFileName(options), true);
}
verifyCompilerOptions();
let diagnosticsProducingTypeChecker: TypeChecker;
let noDiagnosticsTypeChecker: TypeChecker;
programTime += new Date().getTime() - start;
program = {
getSourceFile: getSourceFile,
@@ -430,11 +436,20 @@ module ts {
return;
}
let languageVersion = options.target || ScriptTarget.ES3;
let firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined);
if (firstExternalModuleSourceFile && !options.module) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
let span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
diagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
if (!options.module && languageVersion < ScriptTarget.ES6) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
let span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
diagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_external_modules_unless_the_module_flag_is_provided));
}
}
// Cannot specify module gen target when in es6 or above
if (options.module && languageVersion >= ScriptTarget.ES6) {
diagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_external_modules_into_amd_or_commonjs_when_targeting_es6_or_higher));
}
// there has to be common source directory if user specified --outdir || --sourcRoot
+15 -24
View File
@@ -320,22 +320,16 @@ module ts {
}
function compile(fileNames: string[], compilerOptions: CompilerOptions, compilerHost: CompilerHost) {
ts.ioReadTime = 0;
ts.parseTime = 0;
ts.bindTime = 0;
ts.checkTime = 0;
ts.emitTime = 0;
var start = new Date().getTime();
ioReadTime = 0;
ioWriteTime = 0;
programTime = 0;
bindTime = 0;
checkTime = 0;
emitTime = 0;
var program = createProgram(fileNames, compilerOptions, compilerHost);
var programTime = new Date().getTime() - start;
var exitStatus = compileProgram();
var end = new Date().getTime() - start;
var compileTime = end - programTime;
if (compilerOptions.listFiles) {
forEach(program.getSourceFiles(), file => {
sys.write(file.fileName + sys.newLine);
@@ -356,19 +350,16 @@ module ts {
}
// Individual component times.
// Note: we output 'programTime' as parseTime to match the tsc 1.3 behavior. tsc 1.3
// measured parse time along with read IO as a single counter. We preserve that
// behavior so we can accurately compare times. For actual parse times (in isolation)
// is reported below.
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
// I/O read time and processing time for triple-slash references and module imports, and the reported
// emit time includes I/O write time. We preserve this behavior so we can accurately compare times.
reportTimeStatistic("I/O read", ioReadTime);
reportTimeStatistic("I/O write", ioWriteTime);
reportTimeStatistic("Parse time", programTime);
reportTimeStatistic("Bind time", ts.bindTime);
reportTimeStatistic("Check time", ts.checkTime);
reportTimeStatistic("Emit time", ts.emitTime);
reportTimeStatistic("Parse time w/o IO", ts.parseTime);
reportTimeStatistic("IO read", ts.ioReadTime);
reportTimeStatistic("Compile time", compileTime);
reportTimeStatistic("Total time", end);
reportTimeStatistic("Bind time", bindTime);
reportTimeStatistic("Check time", checkTime);
reportTimeStatistic("Emit time", emitTime);
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
}
return { program, exitStatus };
+6 -1
View File
@@ -944,7 +944,8 @@ module ts {
export interface ExportAssignment extends Declaration, ModuleElement {
isExportEquals?: boolean;
expression: Expression;
expression?: Expression;
type?: TypeNode;
}
export interface FileReference extends TextRange {
@@ -1486,11 +1487,15 @@ module ts {
(t: Type): Type;
}
// @internal
export interface TypeInferences {
primary: Type[]; // Inferences made directly to a type parameter
secondary: Type[]; // Inferences made to a type parameter in a union type
isFixed: boolean; // Whether the type parameter is fixed, as defined in section 4.12.2 of the TypeScript spec
// If a type parameter is fixed, no more inferences can be made for the type parameter
}
// @internal
export interface InferenceContext {
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
inferUnionTypes: boolean; // Infer union types for disjoint candidates (otherwise undefinedType)
+5 -3
View File
@@ -1621,8 +1621,9 @@ module FourSlash {
this.taoInvalidReason = 'verifyIndentationAtCurrentPosition NYI';
var actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition);
if (actual != numberOfSpaces) {
this.raiseError('verifyIndentationAtCurrentPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual);
var lineCol = this.getLineColStringAtPosition(this.currentCaretPosition);
if (actual !== numberOfSpaces) {
this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual);
}
}
@@ -1630,8 +1631,9 @@ module FourSlash {
this.taoInvalidReason = 'verifyIndentationAtPosition NYI';
var actual = this.getIndentation(fileName, position);
var lineCol = this.getLineColStringAtPosition(position);
if (actual !== numberOfSpaces) {
this.raiseError('verifyIndentationAtPosition failed - expected: ' + numberOfSpaces + ', actual: ' + actual);
this.raiseError('verifyIndentationAtPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual);
}
}
+59 -20
View File
@@ -19,15 +19,19 @@ module ts.server {
class ScriptInfo {
svc: ScriptVersionCache;
children: ScriptInfo[] = []; // files referenced by this file
defaultProject: Project; // project to use by default for file
fileWatcher: FileWatcher;
formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions);
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
this.svc = ScriptVersionCache.fromString(content);
}
setFormatOptions(tabSize: number, indentSize: number) {
this.formatCodeOptions.TabSize = tabSize;
this.formatCodeOptions.IndentSize = indentSize;
}
close() {
this.isOpen = false;
}
@@ -153,15 +157,18 @@ module ts.server {
}
}
reloadScript(filename: string, tmpfilename: string, tabSize: number, cb: () => any) {
reloadScript(filename: string, tmpfilename: string, cb: () => any) {
var script = this.getScriptInfo(filename);
if (script) {
script.svc.reloadFromFile(tmpfilename, tabSize, cb);
script.svc.reloadFromFile(tmpfilename, script.formatCodeOptions.TabSize, cb);
}
}
editScript(filename: string, start: number, end: number, newText: string) {
var script = this.getScriptInfo(filename);
if (newText && (newText.length > 0)) {
newText = expandTabs(newText, script.formatCodeOptions.TabSize);
}
if (script) {
script.editContent(start, end, newText);
return;
@@ -365,6 +372,12 @@ module ts.server {
hostInfo: string;
}
export function expandTabs(text: string, tabSize: number) {
var spaces = generateSpaces(tabSize);
return text.replace(/\t/g, spaces);
}
export class ProjectService {
filenameToScriptInfo: ts.Map<ScriptInfo> = {};
// open, non-configured files in two lists
@@ -386,7 +399,13 @@ module ts.server {
}
}
getFormatCodeOptions() {
getFormatCodeOptions(file?: string) {
if (file) {
var info = this.filenameToScriptInfo[file];
if (info) {
return info.formatCodeOptions;
}
}
return this.hostConfiguration.formatCodeOptions;
}
@@ -402,7 +421,7 @@ module ts.server {
}
else {
if (info && (!info.isOpen)) {
info.svc.reloadFromFile(info.fileName, this.hostConfiguration.formatCodeOptions.TabSize);
info.svc.reloadFromFile(info.fileName, info.formatCodeOptions.TabSize);
}
}
}
@@ -412,15 +431,19 @@ module ts.server {
}
setHostConfiguration(args: ts.server.protocol.ConfigureRequestArguments) {
this.hostConfiguration.formatCodeOptions.TabSize = args.tabSize;
this.hostConfiguration.formatCodeOptions.IndentSize = args.indentSize;
this.hostConfiguration.hostInfo = args.hostInfo;
this.log("Host information " + args.hostInfo, "Info");
}
expandTabs(text: string) {
var spaces = generateSpaces(this.hostConfiguration.formatCodeOptions.TabSize);
return text.replace(/\t/g, spaces);
if (args.file) {
var info = this.filenameToScriptInfo[args.file];
if (info) {
info.setFormatOptions(args.tabSize, args.indentSize);
this.log("Host configuration update for file " + args.file + " tab size " + args.tabSize);
}
}
else {
this.hostConfiguration.formatCodeOptions.TabSize = args.tabSize;
this.hostConfiguration.formatCodeOptions.IndentSize = args.indentSize;
this.hostConfiguration.hostInfo = args.hostInfo;
this.log("Host information " + args.hostInfo, "Info");
}
}
closeLog() {
@@ -623,7 +646,7 @@ module ts.server {
/**
* @param filename is absolute pathname
*/
openFile(fileName: string, openedByClient = false) {
openFile(fileName: string, openedByClient: boolean, tabSize?: number) {
fileName = ts.normalizePath(fileName);
var info = ts.lookUp(this.filenameToScriptInfo, fileName);
if (!info) {
@@ -637,12 +660,26 @@ module ts.server {
}
}
if (content !== undefined) {
content = this.expandTabs(content);
var indentSize: number;
if (!tabSize) {
tabSize = this.hostConfiguration.formatCodeOptions.TabSize;
indentSize = this.hostConfiguration.formatCodeOptions.IndentSize;
}
else {
indentSize = tabSize;
}
if (openedByClient) {
this.log("Expanding tabs for file " + fileName + " with tab size " + tabSize.toString());
content = expandTabs(content, tabSize);
}
info = new ScriptInfo(this.host, fileName, content, openedByClient);
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
info.fileWatcher = this.host.watchFile(fileName, _ => { this.watchedFileChanged(fileName); });
}
else {
info.setFormatOptions(tabSize, indentSize);
}
}
}
if (info) {
@@ -658,9 +695,9 @@ module ts.server {
* @param filename is absolute pathname
*/
openClientFile(filename: string) {
openClientFile(filename: string, tabSize?: number) {
// TODO: tsconfig check
var info = this.openFile(filename, true);
var info = this.openFile(filename, true, tabSize);
this.addOpenFile(info);
this.printProjects();
return info;
@@ -760,7 +797,8 @@ module ts.server {
var normRootFilename = ts.normalizePath(rootFilename);
normRootFilename = getAbsolutePath(normRootFilename, dirPath);
if (this.host.fileExists(normRootFilename)) {
var info = this.openFile(normRootFilename);
// TODO: pass true for file exiplicitly opened
var info = this.openFile(normRootFilename, false);
proj.addRoot(info);
}
else {
@@ -1123,6 +1161,7 @@ module ts.server {
reloadFromFile(filename: string, tabSize: number, cb?: () => any) {
var content = ts.sys.readFile(filename);
content = expandTabs(content, tabSize);
this.reload(content);
if (cb)
cb();
+14 -1
View File
@@ -312,6 +312,10 @@ declare module ts.server.protocol {
* 'Sublime Text version 3075'
*/
hostInfo: string;
/**
* If present, tab settings apply only to this file.
*/
file?: string;
}
/**
@@ -329,6 +333,14 @@ declare module ts.server.protocol {
export interface ConfigureResponse extends Response {
}
/**
* Information found in an "open" request.
*/
export interface OpenRequestArgs extends FileRequestArgs {
/** Initial tab size of file. */
tabSize?: number;
}
/**
* Open request; value of command field is "open". Notify the
* server that the client has file open. The server will not
@@ -337,7 +349,8 @@ declare module ts.server.protocol {
* reload messages) when the file changes. Server does not currently
* send a response to an open request.
*/
export interface OpenRequest extends FileRequest {
export interface OpenRequest extends Request {
arguments: OpenRequestArgs;
}
/**
+8 -9
View File
@@ -5,7 +5,7 @@
/// <reference path="editorServices.ts" />
module ts.server {
var spaceCache = [" ", " ", " ", " "];
var spaceCache:string[] = [];
interface StackTraceError extends Error {
stack?: string;
@@ -397,9 +397,9 @@ module ts.server {
};
}
openClientFile(fileName: string) {
openClientFile(fileName: string, tabSize?: number) {
var file = ts.normalizePath(fileName);
this.projectService.openClientFile(file);
this.projectService.openClientFile(file, tabSize);
}
getQuickInfo(line: number, col: number, fileName: string): protocol.QuickInfoResponseBody {
@@ -441,7 +441,7 @@ module ts.server {
// TODO: avoid duplicate code (with formatonkey)
var edits = compilerService.languageService.getFormattingEditsForRange(file, startPosition, endPosition,
this.projectService.getFormatCodeOptions());
this.projectService.getFormatCodeOptions(file));
if (!edits) {
return undefined;
}
@@ -465,7 +465,7 @@ module ts.server {
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var formatOptions = this.projectService.getFormatCodeOptions();
var formatOptions = this.projectService.getFormatCodeOptions(file);
var edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
formatOptions);
// Check whether we should auto-indent. This will be when
@@ -611,8 +611,7 @@ module ts.server {
if (project) {
this.changeSeq++;
// make sure no changes happen before this one is finished
project.compilerService.host.reloadScript(file, tmpfile,
this.projectService.getFormatCodeOptions().TabSize, () => {
project.compilerService.host.reloadScript(file, tmpfile, () => {
this.output(undefined, CommandNames.Reload, reqSeq);
});
}
@@ -756,8 +755,8 @@ module ts.server {
break;
}
case CommandNames.Open: {
var openArgs = <protocol.FileRequestArgs>request.arguments;
this.openClientFile(openArgs.file);
var openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file,openArgs.tabSize);
responseRequired = false;
break;
}
+4
View File
@@ -173,6 +173,10 @@ module ts.BreakpointResolver {
return textSpan(node, (<ThrowStatement>node).expression);
case SyntaxKind.ExportAssignment:
if (!(<ExportAssignment>node).expression) {
return undefined;
}
// span on export = id
return textSpan(node, (<ExportAssignment>node).expression);
+12 -2
View File
@@ -1008,10 +1008,20 @@ module ts.formatting {
return SyntaxKind.Unknown;
}
let internedTabsIndentation: string[];
let internedSpacesIndentation: string[];
var internedSizes: { tabSize: number; indentSize: number };
var internedTabsIndentation: string[];
var internedSpacesIndentation: string[];
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
// reset interned strings if FormatCodeOptions were changed
let resetInternedStrings =
!internedSizes || (internedSizes.tabSize !== options.TabSize || internedSizes.indentSize !== options.IndentSize);
if (resetInternedStrings) {
internedSizes = { tabSize: options.TabSize, indentSize: options.IndentSize };
internedTabsIndentation = internedSpacesIndentation = undefined;
}
if (!options.ConvertTabsToSpaces) {
let tabs = Math.floor(indentation / options.TabSize);
let spaces = indentation - tabs * options.TabSize;
-54
View File
@@ -1,54 +0,0 @@
module ts.formatting {
var internedTabsIndentation: string[];
var internedSpacesIndentation: string[];
export function getIndentationString(indentation: number, options: FormatCodeOptions): string {
if (!options.ConvertTabsToSpaces) {
var tabs = Math.floor(indentation / options.TabSize);
var spaces = indentation - tabs * options.TabSize;
var tabString: string;
if (!internedTabsIndentation) {
internedTabsIndentation = [];
}
if (internedTabsIndentation[tabs] === undefined) {
internedTabsIndentation[tabs] = tabString = repeat('\t', tabs);
}
else {
tabString = internedTabsIndentation[tabs];
}
return spaces ? tabString + repeat(" ", spaces) : tabString;
}
else {
var spacesString: string;
var quotient = Math.floor(indentation / options.IndentSize);
var remainder = indentation % options.IndentSize;
if (!internedSpacesIndentation) {
internedSpacesIndentation = [];
}
if (internedSpacesIndentation[quotient] === undefined) {
spacesString = repeat(" ", options.IndentSize * quotient);
internedSpacesIndentation[quotient] = spacesString;
}
else {
spacesString = internedSpacesIndentation[quotient];
}
return remainder ? spacesString + repeat(" ", remainder) : spacesString;
}
function repeat(value: string, count: number): string {
var s = "";
for (var i = 0; i < count; ++i) {
s += value;
}
return s;
}
}
}
+53 -9
View File
@@ -359,6 +359,7 @@ module ts.formatting {
case SyntaxKind.ModuleBlock:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.TypeLiteral:
case SyntaxKind.TupleType:
case SyntaxKind.CaseBlock:
case SyntaxKind.DefaultClause:
case SyntaxKind.CaseClause:
@@ -370,6 +371,8 @@ module ts.formatting {
case SyntaxKind.ExportAssignment:
case SyntaxKind.ReturnStatement:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ObjectBindingPattern:
return true;
}
return false;
@@ -390,6 +393,7 @@ module ts.formatting {
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
@@ -431,46 +435,85 @@ module ts.formatting {
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.TypeLiteral:
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
case SyntaxKind.CaseBlock:
return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);
case SyntaxKind.CatchClause:
return isCompletedNode((<CatchClause>n).block, sourceFile);
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.CallSignature:
case SyntaxKind.NewExpression:
if (!(<NewExpression>n).arguments) {
return true;
}
// fall through
case SyntaxKind.CallExpression:
case SyntaxKind.ConstructSignature:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.ParenthesizedType:
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
return isCompletedNode((<SignatureDeclaration>n).type, sourceFile);
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.ArrowFunction:
return !(<FunctionLikeDeclaration>n).body || isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
if ((<FunctionLikeDeclaration>n).body) {
return isCompletedNode((<FunctionLikeDeclaration>n).body, sourceFile);
}
if ((<FunctionLikeDeclaration>n).type) {
return isCompletedNode((<FunctionLikeDeclaration>n).type, sourceFile);
}
// Even though type parameters can be unclosed, we can get away with
// having at least a closing paren.
return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile);
case SyntaxKind.ModuleDeclaration:
return (<ModuleDeclaration>n).body && isCompletedNode((<ModuleDeclaration>n).body, sourceFile);
case SyntaxKind.IfStatement:
if ((<IfStatement>n).elseStatement) {
return isCompletedNode((<IfStatement>n).elseStatement, sourceFile);
}
return isCompletedNode((<IfStatement>n).thenStatement, sourceFile);
case SyntaxKind.ExpressionStatement:
return isCompletedNode((<ExpressionStatement>n).expression, sourceFile);
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ComputedPropertyName:
case SyntaxKind.TupleType:
return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile);
case SyntaxKind.IndexSignature:
if ((<IndexSignatureDeclaration>n).type) {
return isCompletedNode((<IndexSignatureDeclaration>n).type, sourceFile);
}
return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile);
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
// there is no such thing as terminator token for CaseClause\DefaultClause so for simplicitly always consider them non-completed
// there is no such thing as terminator token for CaseClause/DefaultClause so for simplicitly always consider them non-completed
return false;
case SyntaxKind.ForStatement:
return isCompletedNode((<ForStatement>n).statement, sourceFile);
case SyntaxKind.ForInStatement:
return isCompletedNode((<ForInStatement>n).statement, sourceFile);
case SyntaxKind.ForOfStatement:
return isCompletedNode((<ForOfStatement>n).statement, sourceFile);
case SyntaxKind.WhileStatement:
return isCompletedNode((<WhileStatement>n).statement, sourceFile);
return isCompletedNode((<IterationStatement>n).statement, sourceFile);
case SyntaxKind.DoStatement:
// rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')';
let hasWhileKeyword = findChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile);
@@ -478,6 +521,7 @@ module ts.formatting {
return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile);
}
return isCompletedNode((<DoStatement>n).statement, sourceFile);
default:
return true;
}
+2
View File
@@ -833,3 +833,5 @@ module ts {
module TypeScript.Services {
export var TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
}
let toolsVersion = "1.4";
+4
View File
@@ -79,6 +79,10 @@ module ts {
};
}
export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): boolean {
return !!findChildOfKind(n, kind, sourceFile);
}
export function findChildOfKind(n: Node, kind: SyntaxKind, sourceFile?: SourceFile): Node {
return forEach(n.getChildren(sourceFile), c => c.kind === kind && c);
}