Merge branch 'master' into es6typings

Conflicts:
	src/compiler/parser.ts
	src/compiler/tsc.ts
	src/harness/harness.ts
	src/harness/projectsRunner.ts
	tests/baselines/reference/templateStringsArrayTypeDefinedInES5Mode.errors.txt
This commit is contained in:
Mohamed Hegazy 2014-11-27 09:59:46 -08:00
commit d3e70ecfbf
732 changed files with 24820 additions and 28528 deletions

1
.gitignore vendored
View File

@ -41,4 +41,5 @@ scripts/debug.bat
scripts/run.bat
scripts/word2md.js
scripts/ior.js
scripts/*.js.map
coverage/

4
bin/lib.core.d.ts vendored
View File

@ -499,6 +499,10 @@ declare var Number: {
POSITIVE_INFINITY: number;
}
interface TemplateStringsArray extends Array<string> {
raw: string[];
}
interface Math {
/** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
E: number;

4
bin/lib.d.ts vendored
View File

@ -499,6 +499,10 @@ declare var Number: {
POSITIVE_INFINITY: number;
}
interface TemplateStringsArray extends Array<string> {
raw: string[];
}
interface Math {
/** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
E: number;

6956
bin/tsc.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,7 +18,7 @@ module ts {
return ModuleInstanceState.NonInstantiated;
}
// 2. const enum declarations don't make module instantiated
else if (node.kind === SyntaxKind.EnumDeclaration && isConstEnumDeclaration(<EnumDeclaration>node)) {
else if (isConstEnumDeclaration(node)) {
return ModuleInstanceState.ConstEnumOnly;
}
// 3. non - exported import declarations
@ -125,9 +125,9 @@ module ts {
: Diagnostics.Duplicate_identifier_0;
forEach(symbol.declarations, declaration => {
file.semanticErrors.push(createDiagnosticForNode(declaration.name, message, getDisplayName(declaration)));
file.semanticDiagnostics.push(createDiagnosticForNode(declaration.name, message, getDisplayName(declaration)));
});
file.semanticErrors.push(createDiagnosticForNode(node.name, message, getDisplayName(node)));
file.semanticDiagnostics.push(createDiagnosticForNode(node.name, message, getDisplayName(node)));
symbol = createSymbol(0, name);
}
@ -148,7 +148,7 @@ module ts {
if (node.name) {
node.name.parent = node;
}
file.semanticErrors.push(createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0],
file.semanticDiagnostics.push(createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0],
Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
}
symbol.exports[prototypeSymbol.name] = prototypeSymbol;
@ -380,6 +380,7 @@ module ts {
break;
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.ShorthandPropertyAssignment:
bindDeclaration(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumMember:
@ -438,7 +439,7 @@ module ts {
bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes, /*isBlockScopeContainer*/ false);
break;
case SyntaxKind.EnumDeclaration:
if (isConstEnumDeclaration(<EnumDeclaration>node)) {
if (isConst(node)) {
bindDeclaration(<Declaration>node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes, /*isBlockScopeContainer*/ false);
}
else {

View File

@ -75,41 +75,44 @@ module ts {
var checker: TypeChecker = {
getProgram: () => program,
getDiagnostics: getDiagnostics,
getGlobalDiagnostics: getGlobalDiagnostics,
getNodeCount: () => sum(program.getSourceFiles(), "nodeCount"),
getIdentifierCount: () => sum(program.getSourceFiles(), "identifierCount"),
getSymbolCount: () => sum(program.getSourceFiles(), "symbolCount"),
getTypeCount: () => typeCount,
checkProgram: checkProgram,
emitFiles: invokeEmitter,
getParentOfSymbol: getParentOfSymbol,
getNarrowedTypeOfSymbol: getNarrowedTypeOfSymbol,
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
getPropertiesOfType: getPropertiesOfType,
getPropertyOfType: getPropertyOfType,
getSignaturesOfType: getSignaturesOfType,
getIndexTypeOfType: getIndexTypeOfType,
getReturnTypeOfSignature: getReturnTypeOfSignature,
getSymbolsInScope: getSymbolsInScope,
getSymbolInfo: getSymbolInfo,
getTypeOfNode: getTypeOfNode,
typeToString: typeToString,
getSymbolDisplayBuilder: getSymbolDisplayBuilder,
symbolToString: symbolToString,
getAugmentedPropertiesOfType: getAugmentedPropertiesOfType,
getRootSymbols: getRootSymbols,
getContextualType: getContextualType,
getFullyQualifiedName: getFullyQualifiedName,
getResolvedSignature: getResolvedSignature,
getEnumMemberValue: getEnumMemberValue,
isValidPropertyAccess: isValidPropertyAccess,
getSignatureFromDeclaration: getSignatureFromDeclaration,
isImplementationOfOverload: isImplementationOfOverload,
getAliasedSymbol: resolveImport,
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
isEmitBlocked: isEmitBlocked
emitFiles: invokeEmitter,
getDiagnostics,
getDeclarationDiagnostics,
getGlobalDiagnostics,
checkProgram,
getParentOfSymbol,
getNarrowedTypeOfSymbol,
getDeclaredTypeOfSymbol,
getPropertiesOfType,
getPropertyOfType,
getSignaturesOfType,
getIndexTypeOfType,
getReturnTypeOfSignature,
getSymbolsInScope,
getSymbolInfo,
getShorthandAssignmentValueSymbol,
getTypeOfNode,
typeToString,
getSymbolDisplayBuilder,
symbolToString,
getAugmentedPropertiesOfType,
getRootSymbols,
getContextualType,
getFullyQualifiedName,
getResolvedSignature,
getEnumMemberValue,
isValidPropertyAccess,
getSignatureFromDeclaration,
isImplementationOfOverload,
getAliasedSymbol: resolveImport,
hasEarlyErrors,
isEmitBlocked,
};
var undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
@ -883,13 +886,13 @@ module ts {
if (accessibleSymbolChain) {
var hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
if (!hasAccessibleDeclarations) {
return {
return <SymbolAccessiblityResult>{
accessibility: SymbolAccessibility.NotAccessible,
errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning),
errorModuleName: symbol !== initialSymbol ? symbolToString(symbol, enclosingDeclaration, SymbolFlags.Namespace) : undefined,
};
}
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible: hasAccessibleDeclarations.aliasesToMakeVisible };
return hasAccessibleDeclarations;
}
// If we haven't got the accessible symbol, it doesn't mean the symbol is actually inaccessible.
@ -946,12 +949,12 @@ module ts {
(declaration.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>declaration));
}
function hasVisibleDeclarations(symbol: Symbol): { aliasesToMakeVisible?: ImportDeclaration[]; } {
function hasVisibleDeclarations(symbol: Symbol): SymbolVisibilityResult {
var aliasesToMakeVisible: ImportDeclaration[];
if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
return undefined;
}
return { aliasesToMakeVisible: aliasesToMakeVisible };
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
function getIsDeclarationVisible(declaration: Declaration) {
if (!isDeclarationVisible(declaration)) {
@ -980,14 +983,33 @@ module ts {
}
}
function isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult {
function isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult {
// get symbol of the first identifier of the entityName
var meaning: SymbolFlags;
if (entityName.parent.kind === SyntaxKind.TypeQuery) {
// Typeof value
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
}
else if (entityName.kind === SyntaxKind.QualifiedName ||
entityName.parent.kind === SyntaxKind.ImportDeclaration) {
// Left identifier from type reference or TypeAlias
// Entity name of the import declaration
meaning = SymbolFlags.Namespace;
}
else {
// Type Reference or TypeAlias entity = Identifier
meaning = SymbolFlags.Type;
}
var firstIdentifier = getFirstIdentifier(entityName);
var symbolOfNameSpace = resolveName(entityName.parent, (<Identifier>firstIdentifier).text, SymbolFlags.Namespace, Diagnostics.Cannot_find_name_0, firstIdentifier);
var symbol = resolveName(enclosingDeclaration, (<Identifier>firstIdentifier).text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
// Verify if the symbol is accessible
var hasNamespaceDeclarationsVisibile = hasVisibleDeclarations(symbolOfNameSpace);
return hasNamespaceDeclarationsVisibile ?
{ accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible: hasNamespaceDeclarationsVisibile.aliasesToMakeVisible } :
{ accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: declarationNameToString(<Identifier>firstIdentifier) };
return hasVisibleDeclarations(symbol) || <SymbolVisibilityResult>{
accessibility: SymbolAccessibility.NotAccessible,
errorSymbolName: getTextOfNode(firstIdentifier),
errorNode: firstIdentifier
};
}
function releaseStringWriter(writer: StringSymbolWriter) {
@ -1599,6 +1621,7 @@ module ts {
case SyntaxKind.IndexSignature:
case SyntaxKind.Parameter:
case SyntaxKind.ModuleBlock:
case SyntaxKind.TypeParameter:
return isDeclarationVisible(node.parent);
// Source file is always visible
@ -1665,6 +1688,13 @@ module ts {
}
return type;
}
// If it is a short-hand property assignment; Use the type of the identifier
if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) {
var type = checkIdentifier(<Identifier>declaration.name);
return type
}
// Rest parameters default to type any[], other parameters default to type any
var type = declaration.flags & NodeFlags.Rest ? createArrayType(anyType) : anyType;
checkImplicitAny(type);
@ -1775,7 +1805,7 @@ module ts {
}
else {
// If there are no specified types, try to infer it from the body of the get accessor if it exists.
if (getter) {
if (getter && getter.body) {
type = getReturnTypeFromBody(getter);
}
// Otherwise, fall back to 'any'.
@ -2399,7 +2429,7 @@ module ts {
}
// Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
// necessary, maps primtive types and type parameters are to their apparent types, and augments with properties from
// necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
// Object and Function as appropriate.
function getPropertyOfType(type: Type, name: string): Symbol {
if (type.flags & TypeFlags.Union) {
@ -2434,7 +2464,7 @@ module ts {
}
// Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
// maps primtive types and type parameters are to their apparent types.
// maps primitive types and type parameters are to their apparent types.
function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] {
return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
}
@ -2447,7 +2477,7 @@ module ts {
}
// Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and
// maps primtive types and type parameters are to their apparent types.
// maps primitive types and type parameters are to their apparent types.
function getIndexTypeOfType(type: Type, kind: IndexKind): Type {
return getIndexTypeOfObjectOrUnionType(getApparentType(type), kind);
}
@ -3225,9 +3255,9 @@ module ts {
// TYPE CHECKING
var subtypeRelation: Map<Ternary> = {};
var assignableRelation: Map<Ternary> = {};
var identityRelation: Map<Ternary> = {};
var subtypeRelation: Map<boolean> = {};
var assignableRelation: Map<boolean> = {};
var identityRelation: Map<boolean> = {};
function isTypeIdenticalTo(source: Type, target: Type): boolean {
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
@ -3262,7 +3292,7 @@ module ts {
function checkTypeRelatedTo(
source: Type,
target: Type,
relation: Map<Ternary>,
relation: Map<boolean>,
errorNode: Node,
headMessage?: DiagnosticMessage,
containingMessageChain?: DiagnosticMessageChain): boolean {
@ -3270,6 +3300,7 @@ module ts {
var errorInfo: DiagnosticMessageChain;
var sourceStack: ObjectType[];
var targetStack: ObjectType[];
var maybeStack: Map<boolean>[];
var expandingFlags: number;
var depth = 0;
var overflow = false;
@ -3428,12 +3459,12 @@ module ts {
var id = source.id + "," + target.id;
var related = relation[id];
if (related !== undefined) {
return related;
return related ? Ternary.True : Ternary.False;
}
if (depth > 0) {
for (var i = 0; i < depth; i++) {
// If source and target are already being compared, consider them related with assumptions
if (source === sourceStack[i] && target === targetStack[i]) {
if (maybeStack[i][id]) {
return Ternary.Maybe;
}
}
@ -3445,16 +3476,19 @@ module ts {
else {
sourceStack = [];
targetStack = [];
maybeStack = [];
expandingFlags = 0;
}
sourceStack[depth] = source;
targetStack[depth] = target;
maybeStack[depth] = {};
maybeStack[depth][id] = true;
depth++;
var saveExpandingFlags = expandingFlags;
if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack)) expandingFlags |= 1;
if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack)) expandingFlags |= 2;
if (expandingFlags === 3) {
var result = Ternary.True;
var result = Ternary.Maybe;
}
else {
var result = propertiesRelatedTo(source, target, reportErrors);
@ -3473,9 +3507,18 @@ module ts {
}
expandingFlags = saveExpandingFlags;
depth--;
// Only cache results that are free of assumptions
if (result !== Ternary.Maybe) {
relation[id] = result;
if (result) {
var maybeCache = maybeStack[depth];
// If result is definitely true, copy assumptions to global cache, else copy to next level up
var destinationCache = result === Ternary.True || depth === 0 ? relation : maybeStack[depth - 1];
for (var p in maybeCache) {
destinationCache[p] = maybeCache[p];
}
}
else {
// A false result goes straight into global cache (when something is false under assumptions it
// will also be false without assumptions)
relation[id] = false;
}
return result;
}
@ -5000,7 +5043,15 @@ module ts {
if (hasProperty(members, id)) {
var member = members[id];
if (member.flags & SymbolFlags.Property) {
var type = checkExpression((<PropertyDeclaration>member.declarations[0]).initializer, contextualMapper);
var memberDecl = <PropertyDeclaration>member.declarations[0];
var type: Type;
if (memberDecl.kind === SyntaxKind.PropertyAssignment) {
type = checkExpression(memberDecl.initializer, contextualMapper);
}
else {
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
type = checkExpression(memberDecl.name, contextualMapper);
}
var prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
prop.declarations = member.declarations;
prop.parent = member.parent;
@ -5403,7 +5454,7 @@ module ts {
return typeArgumentsAreAssignable;
}
function checkApplicableSignature(node: CallLikeExpression, args: Node[], signature: Signature, relation: Map<Ternary>, excludeArgument: boolean[], reportErrors: boolean) {
function checkApplicableSignature(node: CallLikeExpression, args: Node[], signature: Signature, relation: Map<boolean>, excludeArgument: boolean[], reportErrors: boolean) {
for (var i = 0; i < args.length; i++) {
var arg = args[i];
var argType: Type;
@ -5597,7 +5648,7 @@ module ts {
return resolveErrorCall(node);
function chooseOverload(candidates: Signature[], relation: Map<Ternary>) {
function chooseOverload(candidates: Signature[], relation: Map<boolean>) {
for (var i = 0; i < candidates.length; i++) {
if (!hasCorrectArity(node, args, candidates[i])) {
continue;
@ -7501,10 +7552,13 @@ module ts {
// for (var VarDecl in Expr) Statement
// VarDecl must be a variable declaration without a type annotation that declares a variable of type Any,
// and Expr must be an expression of type Any, an object type, or a type parameter type.
if (node.declaration) {
checkVariableDeclaration(node.declaration);
if (node.declaration.type) {
error(node.declaration, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
if (node.declarations) {
if (node.declarations.length >= 1) {
var decl = node.declarations[0];
checkVariableDeclaration(decl);
if (decl.type) {
error(decl, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation);
}
}
}
@ -7953,7 +8007,7 @@ module ts {
var enumType = getDeclaredTypeOfSymbol(enumSymbol);
var autoValue = 0;
var ambient = isInAmbientContext(node);
var enumIsConst = isConstEnumDeclaration(node);
var enumIsConst = isConst(node);
forEach(node.members, member => {
// TODO(jfreeman): Check that it is not a computed name
@ -8124,10 +8178,10 @@ module ts {
var firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind);
if (node === firstDeclaration) {
if (enumSymbol.declarations.length > 1) {
var enumIsConst = isConstEnumDeclaration(node);
var enumIsConst = isConst(node);
// check that const is placed\omitted on all enum declarations
forEach(enumSymbol.declarations, decl => {
if (isConstEnumDeclaration(<EnumDeclaration>decl) !== enumIsConst) {
if (isConstEnumDeclaration(decl) !== enumIsConst) {
error(decl.name, Diagnostics.Enum_declarations_must_all_be_const_or_non_const);
}
});
@ -8492,6 +8546,12 @@ module ts {
return getSortedDiagnostics();
}
function getDeclarationDiagnostics(targetSourceFile: SourceFile): Diagnostic[] {
var resolver = createResolver();
checkSourceFile(targetSourceFile);
return ts.getDeclarationDiagnostics(program, resolver, targetSourceFile);
}
function getGlobalDiagnostics(): Diagnostic[] {
return filter(getSortedDiagnostics(), d => !d.file);
}
@ -8816,6 +8876,16 @@ module ts {
return undefined;
}
function getShorthandAssignmentValueSymbol(location: Node): Symbol {
// The function returns a value symbol of an identifier in the short-hand property assignment.
// This is necessary as an identifier in short-hand property assignment can contains two meaning:
// property name and property value.
if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) {
return resolveEntityName(location, (<ShortHandPropertyDeclaration>location).name, SymbolFlags.Value);
}
return undefined;
}
function getTypeOfNode(node: Node): Type {
if (isInsideWithStatementBody(node)) {
// We cannot answer semantic questions within a with block, do not proceed any further
@ -9075,26 +9145,30 @@ module ts {
getSymbolDisplayBuilder().buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags);
}
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver: EmitResolver = {
function createResolver(): EmitResolver {
return {
getProgram: () => program,
getLocalNameOfContainer: getLocalNameOfContainer,
getExpressionNamePrefix: getExpressionNamePrefix,
getExportAssignmentName: getExportAssignmentName,
isReferencedImportDeclaration: isReferencedImportDeclaration,
getNodeCheckFlags: getNodeCheckFlags,
getEnumMemberValue: getEnumMemberValue,
isTopLevelValueImportWithEntityName: isTopLevelValueImportWithEntityName,
hasSemanticErrors: hasSemanticErrors,
isEmitBlocked: isEmitBlocked,
isDeclarationVisible: isDeclarationVisible,
isImplementationOfOverload: isImplementationOfOverload,
writeTypeAtLocation: writeTypeAtLocation,
writeReturnTypeOfSignatureDeclaration: writeReturnTypeOfSignatureDeclaration,
isSymbolAccessible: isSymbolAccessible,
isImportDeclarationEntityNameReferenceDeclarationVisibile: isImportDeclarationEntityNameReferenceDeclarationVisibile,
getConstantValue: getConstantValue,
getLocalNameOfContainer,
getExpressionNamePrefix,
getExportAssignmentName,
isReferencedImportDeclaration,
getNodeCheckFlags,
getEnumMemberValue,
isTopLevelValueImportWithEntityName,
hasSemanticErrors,
isEmitBlocked,
isDeclarationVisible,
isImplementationOfOverload,
writeTypeAtLocation,
writeReturnTypeOfSignatureDeclaration,
isSymbolAccessible,
isEntityNameVisible,
getConstantValue,
};
}
function invokeEmitter(targetSourceFile?: SourceFile) {
var resolver = createResolver();
checkProgram();
return emitFiles(resolver, targetSourceFile);
}
@ -9103,7 +9177,7 @@ module ts {
// Bind all source files and propagate errors
forEach(program.getSourceFiles(), file => {
bindSourceFile(file);
forEach(file.semanticErrors, addDiagnostic);
forEach(file.semanticDiagnostics, addDiagnostic);
});
// Initialize global symbol table
forEach(program.getSourceFiles(), file => {

View File

@ -153,9 +153,9 @@ module ts {
parseStrings(commandLine);
return {
options: options,
filenames: filenames,
errors: errors
options,
filenames,
errors
};
function parseStrings(args: string[]) {

View File

@ -258,9 +258,9 @@ module ts {
}
return {
file: file,
start: start,
length: length,
file,
start,
length,
messageText: text,
category: message.category,
@ -335,12 +335,12 @@ module ts {
}
return {
file: file,
start: start,
length: length,
code: code,
category: category,
messageText: messageText
file,
start,
length,
code,
category,
messageText
};
}
@ -459,6 +459,10 @@ module ts {
return normalizedPathComponents(path, rootLength);
}
export function getNormalizedAbsolutePath(filename: string, currentDirectory: string) {
return getNormalizedPathFromPathComponents(getNormalizedPathComponents(filename, currentDirectory));
}
export function getNormalizedPathFromPathComponents(pathComponents: string[]) {
if (pathComponents && pathComponents.length) {
return pathComponents[0] + pathComponents.slice(1).join(directorySeparator);

View File

@ -122,6 +122,10 @@ module ts {
let_declarations_can_only_be_declared_inside_a_block: { code: 1157, category: DiagnosticCategory.Error, key: "'let' declarations can only be declared inside a block." },
Invalid_template_literal_expected: { code: 1158, category: DiagnosticCategory.Error, key: "Invalid template literal; expected '}'" },
Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1159, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." },
Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
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." },
@ -270,28 +274,18 @@ module ts {
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." },
Type_alias_name_cannot_be_0: { code: 2457, category: DiagnosticCategory.Error, key: "Type alias name cannot be '{0}'" },
An_AMD_module_cannot_have_multiple_name_assignments: { code: 2458, category: DiagnosticCategory.Error, key: "An AMD module cannot have multiple name assignments." },
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}'." },
Type_parameter_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4003, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4005, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4006, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'." },
Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4007, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1: { code: 4008, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'." },
Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4009, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1: { code: 4010, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public static method from exported class has or is using private name '{1}'." },
Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4011, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1: { code: 4012, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of public method from exported class has or is using private name '{1}'." },
Type_parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2: { code: 4013, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1: { code: 4014, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of method from exported interface has or is using private name '{1}'." },
Type_parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2: { code: 4015, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'." },
Type_parameter_0_of_exported_function_has_or_is_using_private_name_1: { code: 4016, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported function has or is using private name '{1}'." },
Implements_clause_of_exported_class_0_has_or_is_using_name_1_from_private_module_2: { code: 4017, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using name '{1}' from private module '{2}'." },
Extends_clause_of_exported_class_0_has_or_is_using_name_1_from_private_module_2: { code: 4018, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using name '{1}' from private module '{2}'." },
Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4019, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." },
Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 4020, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." },
Extends_clause_of_exported_interface_0_has_or_is_using_name_1_from_private_module_2: { code: 4021, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using name '{1}' from private module '{2}'." },
Extends_clause_of_exported_interface_0_has_or_is_using_private_name_1: { code: 4022, category: DiagnosticCategory.Error, key: "Extends clause of exported interface '{0}' has or is using private name '{1}'." },
Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named: { code: 4023, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from external module {2} but cannot be named." },
Exported_variable_0_has_or_is_using_name_1_from_private_module_2: { code: 4024, category: DiagnosticCategory.Error, key: "Exported variable '{0}' has or is using name '{1}' from private module '{2}'." },
@ -349,8 +343,6 @@ 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}'." },
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.", isEarly: true },

View File

@ -479,6 +479,22 @@
"category": "Error",
"code": 1159
},
"Unterminated template literal.": {
"category": "Error",
"code": 1160
},
"Unterminated regular expression literal.": {
"category": "Error",
"code": 1161
},
"An object member cannot be declared optional.": {
"category": "Error",
"code": 1162
},
"'yield' expression must be contained_within a generator declaration.": {
"category": "Error",
"code": 1163
},
"Duplicate identifier '{0}'.": {
"category": "Error",
@ -1076,83 +1092,47 @@
"category": "Error",
"code": 2457
},
"An AMD module cannot have multiple name assignments.": {
"category": "Error",
"code": 2458
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
},
"Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4001
},
"Type parameter '{0}' of exported class has or is using private name '{1}'.": {
"category": "Error",
"code": 4002
},
"Type parameter '{0}' of exported interface has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4003
},
"Type parameter '{0}' of exported interface has or is using private name '{1}'.": {
"category": "Error",
"code": 4004
},
"Type parameter '{0}' of constructor signature from exported interface has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4005
},
"Type parameter '{0}' of constructor signature from exported interface has or is using private name '{1}'.": {
"category": "Error",
"code": 4006
},
"Type parameter '{0}' of call signature from exported interface has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4007
},
"Type parameter '{0}' of call signature from exported interface has or is using private name '{1}'.": {
"category": "Error",
"code": 4008
},
"Type parameter '{0}' of public static method from exported class has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4009
},
"Type parameter '{0}' of public static method from exported class has or is using private name '{1}'.": {
"category": "Error",
"code": 4010
},
"Type parameter '{0}' of public method from exported class has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4011
},
"Type parameter '{0}' of public method from exported class has or is using private name '{1}'.": {
"category": "Error",
"code": 4012
},
"Type parameter '{0}' of method from exported interface has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4013
},
"Type parameter '{0}' of method from exported interface has or is using private name '{1}'.": {
"category": "Error",
"code": 4014
},
"Type parameter '{0}' of exported function has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4015
},
"Type parameter '{0}' of exported function has or is using private name '{1}'.": {
"category": "Error",
"code": 4016
},
"Implements clause of exported class '{0}' has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4017
},
"Extends clause of exported class '{0}' has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4018
},
"Implements clause of exported class '{0}' has or is using private name '{1}'.": {
"category": "Error",
"code": 4019
@ -1161,10 +1141,6 @@
"category": "Error",
"code": 4020
},
"Extends clause of exported interface '{0}' has or is using name '{1}' from private module '{2}'.": {
"category": "Error",
"code": 4021
},
"Extends clause of exported interface '{0}' has or is using private name '{1}'.": {
"category": "Error",
"code": 4022
@ -1393,14 +1369,6 @@
"category": "Error",
"code": 4078
},
"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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -553,7 +553,7 @@ module ts {
while (true) {
if (pos >= len) {
result += text.substring(start, pos);
error(Diagnostics.Unexpected_end_of_text);
error(Diagnostics.Unterminated_string_literal);
break;
}
var ch = text.charCodeAt(pos);
@ -593,7 +593,7 @@ module ts {
while (true) {
if (pos >= len) {
contents += text.substring(start, pos);
error(Diagnostics.Unexpected_end_of_text);
error(Diagnostics.Unterminated_template_literal);
resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail;
break;
}
@ -931,12 +931,12 @@ module ts {
value = 0;
}
tokenValue = "" + value;
return SyntaxKind.NumericLiteral;
return token = SyntaxKind.NumericLiteral;
}
// Try to parse as an octal
if (pos + 1 < len && isOctalDigit(text.charCodeAt(pos + 1))) {
tokenValue = "" + scanOctalDigits();
return SyntaxKind.NumericLiteral;
return token = SyntaxKind.NumericLiteral;
}
// This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero
// can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being
@ -1066,19 +1066,19 @@ module ts {
var inEscape = false;
var inCharacterClass = false;
while (true) {
// If we've hit EOF without closing off the regex,
// simply return the token we originally parsed.
// If we reach the end of a file, or hit a newline, then this is an unterminated
// regex. Report error and return what we have so far.
if (p >= len) {
return token;
error(Diagnostics.Unterminated_regular_expression_literal)
break;
}
var ch = text.charCodeAt(p);
// Line breaks are not permissible in the middle of a RegExp.
if (isLineBreak(ch)) {
return token;
error(Diagnostics.Unterminated_regular_expression_literal)
break;
}
if (inEscape) {
// Parsing an escape character;
// reset the flag and just advance to the next char.
@ -1087,6 +1087,7 @@ module ts {
else if (ch === CharacterCodes.slash && !inCharacterClass) {
// A slash within a character class is permissible,
// but in general it signals the end of the regexp literal.
p++;
break;
}
else if (ch === CharacterCodes.openBracket) {
@ -1100,8 +1101,8 @@ module ts {
}
p++;
}
p++;
while (isIdentifierPart(text.charCodeAt(p))) {
while (p < len && isIdentifierPart(text.charCodeAt(p))) {
p++;
}
pos = p;
@ -1166,13 +1167,13 @@ module ts {
hasPrecedingLineBreak: () => precedingLineBreak,
isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
reScanGreaterToken: reScanGreaterToken,
reScanSlashToken: reScanSlashToken,
reScanTemplateToken: reScanTemplateToken,
scan: scan,
setText: setText,
setTextPos: setTextPos,
tryScan: tryScan,
reScanGreaterToken,
reScanSlashToken,
reScanTemplateToken,
scan,
setText,
setTextPos,
tryScan,
};
}
}

View File

@ -99,14 +99,14 @@ var sys: System = (function () {
}
return {
args: args,
args,
newLine: "\r\n",
useCaseSensitiveFileNames: false,
write(s: string): void {
WScript.StdOut.Write(s);
},
readFile: readFile,
writeFile: writeFile,
readFile,
writeFile,
resolvePath(path: string): string {
return fso.GetAbsolutePathName(path);
},
@ -191,8 +191,8 @@ var sys: System = (function () {
// 1 is a standard descriptor for stdout
_fs.writeSync(1, s);
},
readFile: readFile,
writeFile: writeFile,
readFile,
writeFile,
watchFile: (fileName, callback) => {
// watchFile polls a file every 250ms, picking up file notifications.
_fs.watchFile(fileName, { persistent: true, interval: 250 }, fileChanged);

View File

@ -192,12 +192,12 @@ module ts {
}
return {
getSourceFile: getSourceFile,
getSourceFile,
getDefaultLibFilename: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts"),
writeFile: writeFile,
writeFile,
getCurrentDirectory: () => currentDirectory || (currentDirectory = sys.getCurrentDirectory()),
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
getCanonicalFileName: getCanonicalFileName,
getCanonicalFileName,
getNewLine: () => sys.newLine
};
}
@ -368,7 +368,7 @@ module ts {
else {
var emitStart = new Date().getTime();
var emitOutput = checker.emitFiles();
var emitErrors = emitOutput.errors;
var emitErrors = emitOutput.diagnostics;
exitStatus = emitOutput.emitResultStatus;
var reportStart = new Date().getTime();
errors = concatenate(errors, emitErrors);
@ -394,7 +394,7 @@ module ts {
reportTimeStatistic("Total time", reportStart - parseStart);
}
return { program: program, exitStatus: exitStatus }
return { program, exitStatus };
}
function printVersion() {

View File

@ -167,6 +167,7 @@ module ts {
ArrayLiteral,
ObjectLiteral,
PropertyAssignment,
ShorthandPropertyAssignment,
PropertyAccess,
IndexedAccess,
CallExpression,
@ -182,6 +183,7 @@ module ts {
ConditionalExpression,
TemplateExpression,
TemplateSpan,
YieldExpression,
OmittedExpression,
// Element
Block,
@ -255,40 +257,60 @@ module ts {
}
export const enum NodeFlags {
Export = 0x00000001, // Declarations
Ambient = 0x00000002, // Declarations
QuestionMark = 0x00000004, // Parameter/Property/Method
Rest = 0x00000008, // Parameter
Public = 0x00000010, // Property/Method
Private = 0x00000020, // Property/Method
Protected = 0x00000040, // Property/Method
Static = 0x00000080, // Property/Method
MultiLine = 0x00000100, // Multi-line array or object literal
Synthetic = 0x00000200, // Synthetic node (for full fidelity)
DeclarationFile = 0x00000400, // Node is a .d.ts file
Let = 0x00000800, // Variable declaration
Const = 0x00001000, // Variable declaration
Export = 0x00000001, // Declarations
Ambient = 0x00000002, // Declarations
QuestionMark = 0x00000004, // Parameter/Property/Method
Rest = 0x00000008, // Parameter
Public = 0x00000010, // Property/Method
Private = 0x00000020, // Property/Method
Protected = 0x00000040, // Property/Method
Static = 0x00000080, // Property/Method
MultiLine = 0x00000100, // Multi-line array or object literal
Synthetic = 0x00000200, // Synthetic node (for full fidelity)
DeclarationFile = 0x00000400, // Node is a .d.ts file
Let = 0x00000800, // Variable declaration
Const = 0x00001000, // Variable declaration
OctalLiteral = 0x00002000,
Generator = 0x00004000,
YieldStar = 0x00008000,
Modifier = Export | Ambient | Public | Private | Protected | Static,
AccessibilityModifier = Public | Private | Protected,
BlockScoped = Let | Const
}
export const enum ParserContextFlags {
// Set if this node was parsed in strict mode. Used for grammar error checks, as well as
// checking if the node can be reused in incremental settings.
StrictMode = 1 << 0,
DisallowIn = 1 << 1,
Yield = 1 << 2,
GeneratorParameter = 1 << 3,
}
export interface Node extends TextRange {
kind: SyntaxKind;
flags: NodeFlags;
// Specific context the parser was in when this node was created. Normally undefined.
// Only set when the parser was in some interesting context (like async/yield).
parserContextFlags?: ParserContextFlags;
id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
symbol?: Symbol; // Symbol declared by node (initialized by binding)
locals?: SymbolTable; // Locals associated with node (initialized by binding)
nextContainer?: Node; // Next container in declaration order (initialized by binding)
localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
modifiers?: ModifiersArray; // Array of modifiers
}
export interface NodeArray<T> extends Array<T>, TextRange {
hasTrailingComma?: boolean;
}
export interface ModifiersArray extends Array<Node> {
flags: number;
}
export interface Identifier extends Node {
text: string; // Text of identifier (with escapes converted to characters)
}
@ -320,6 +342,9 @@ module ts {
export interface TypeParameterDeclaration extends Declaration {
name: Identifier;
constraint?: TypeNode;
// For error recovery purposes.
expression?: Expression;
}
export interface SignatureDeclaration extends Declaration, ParsedSignature { }
@ -335,6 +360,10 @@ module ts {
initializer?: Expression;
}
export interface ShortHandPropertyDeclaration extends Declaration {
name: Identifier;
}
export interface ParameterDeclaration extends VariableDeclaration { }
/**
@ -411,6 +440,10 @@ module ts {
operator: SyntaxKind;
operand: Expression;
}
export interface YieldExpression extends Expression {
expression: Expression;
}
export interface BinaryExpression extends Expression {
left: Expression;
@ -530,7 +563,7 @@ module ts {
}
export interface ForInStatement extends IterationStatement {
declaration?: VariableDeclaration;
declarations?: NodeArray<VariableDeclaration>;
variable?: Expression;
expression: Expression;
}
@ -575,6 +608,7 @@ module ts {
export interface CatchBlock extends Block {
variable: Identifier;
type?: TypeNode;
}
export interface ClassDeclaration extends Declaration {
@ -637,9 +671,19 @@ module ts {
getPositionFromLineAndCharacter(line: number, character: number): number;
getLineStarts(): number[];
amdDependencies: string[];
amdModuleName: string;
referencedFiles: FileReference[];
syntacticErrors: Diagnostic[];
semanticErrors: Diagnostic[];
semanticDiagnostics: Diagnostic[];
// Parse errors refer specifically to things the parser could not understand at all (like
// missing tokens, or tokens it didn't know how to deal with). Grammar errors are for
// things the parser understood, but either the ES6 or TS grammars do not allow (like
// putting an 'public' modifier on a 'class declaration').
parseDiagnostics: Diagnostic[];
grammarDiagnostics: Diagnostic[];
// Returns all
getSyntacticDiagnostics(): Diagnostic[];
hasNoDefaultLib: boolean;
externalModuleIndicator: Node; // The first node that causes this file to be an external module
nodeCount: number;
@ -695,13 +739,14 @@ module ts {
export interface EmitResult {
emitResultStatus: EmitReturnStatus;
errors: Diagnostic[];
diagnostics: Diagnostic[];
sourceMaps: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps
}
export interface TypeChecker {
getProgram(): Program;
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
getDeclarationDiagnostics(sourceFile: SourceFile): Diagnostic[];
getGlobalDiagnostics(): Diagnostic[];
getNodeCount(): number;
getIdentifierCount(): number;
@ -719,6 +764,7 @@ module ts {
getReturnTypeOfSignature(signature: Signature): Type;
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
getSymbolInfo(node: Node): Symbol;
getShorthandAssignmentValueSymbol(location: Node): Symbol;
getTypeOfNode(node: Node): Type;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
@ -727,11 +773,11 @@ module ts {
getAugmentedPropertiesOfType(type: Type): Symbol[];
getRootSymbols(symbol: Symbol): Symbol[];
getContextualType(node: Node): Type;
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
isEmitBlocked(sourceFile?: SourceFile): boolean;
// Returns the constant value of this enum member, or 'undefined' if the enum member has a computed value.
getEnumMemberValue(node: EnumMember): number;
@ -798,11 +844,15 @@ module ts {
CannotBeNamed
}
export interface SymbolAccessiblityResult {
export interface SymbolVisibilityResult {
accessibility: SymbolAccessibility;
errorSymbolName?: string // Optional symbol name that results in error
errorModuleName?: string // If the symbol is not visible from module, module's name
aliasesToMakeVisible?: ImportDeclaration[]; // aliases that need to have this symbol visible
errorSymbolName?: string; // Optional symbol name that results in error
errorNode?: Node; // optional node that results in error
}
export interface SymbolAccessiblityResult extends SymbolVisibilityResult {
errorModuleName?: string // If the symbol is not visible from module, module's name
}
export interface EmitResolver {
@ -820,7 +870,7 @@ module ts {
writeTypeAtLocation(location: Node, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
isImportDeclarationEntityNameReferenceDeclarationVisibile(entityName: EntityName): SymbolAccessiblityResult;
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: PropertyAccess | IndexedAccess): number;
isEmitBlocked(sourceFile?: SourceFile): boolean;

View File

@ -215,7 +215,7 @@ module FourSlash {
}
public setCancelled(numberOfCalls: number = 0): void {
TypeScript.Debug.assert(numberOfCalls >= 0);
ts.Debug.assert(numberOfCalls >= 0);
this.numberOfCallsBeforeCancellation = numberOfCalls;
}
@ -239,7 +239,7 @@ module FourSlash {
// This function creates IScriptSnapshot object for testing getPreProcessedFileInfo
// Return object may lack some functionalities for other purposes.
function createScriptSnapShot(sourceText: string): TypeScript.IScriptSnapshot {
function createScriptSnapShot(sourceText: string): ts.IScriptSnapshot {
return {
getText: (start: number, end: number) => {
return sourceText.substr(start, end - start);
@ -250,8 +250,8 @@ module FourSlash {
getLineStartPositions: () => {
return <number[]>[];
},
getChangeRange: (oldSnapshot: TypeScript.IScriptSnapshot) => {
return <TypeScript.TextChangeRange>undefined;
getChangeRange: (oldSnapshot: ts.IScriptSnapshot) => {
return <ts.TextChangeRange>undefined;
}
};
}
@ -262,7 +262,7 @@ module FourSlash {
private languageService: ts.LanguageService;
// A reference to the language service's compiler state's compiler instance
private compiler: () => { getSyntaxTree(fileName: string): TypeScript.SyntaxTree; getSourceUnit(fileName: string): TypeScript.SourceUnitSyntax; };
private compiler: () => { getSyntaxTree(fileName: string): ts.SourceFile };
// The current caret position in the active file
public currentCaretPosition = 0;
@ -403,8 +403,9 @@ module FourSlash {
public goToPosition(pos: number) {
this.currentCaretPosition = pos;
var lineCharPos = TypeScript.LineMap1.fromString(this.getCurrentFileContent()).getLineAndCharacterFromPosition(pos);
this.scenarioActions.push('<MoveCaretToLineAndChar LineNumber="' + (lineCharPos.line() + 1) + '" CharNumber="' + (lineCharPos.character() + 1) + '" />');
var lineStarts = ts.computeLineStarts(this.getCurrentFileContent());
var lineCharPos = ts.getLineAndCharacterOfPosition(lineStarts, pos);
this.scenarioActions.push('<MoveCaretToLineAndChar LineNumber="' + lineCharPos.line + '" CharNumber="' + lineCharPos.character + '" />');
}
public moveCaretRight(count = 1) {
@ -748,29 +749,6 @@ module FourSlash {
}
}
public verifyImplementorsCountIs(count: number, localFilesOnly: boolean = true) {
var implementors = this.getImplementorsAtCaret();
var implementorsCount = 0;
if (localFilesOnly) {
var localFiles = this.testData.files.map<string>(file => file.fileName);
// Count only the references in local files. Filter the ones in lib and other files.
implementors.forEach((entry) => {
if (localFiles.some((filename) => filename === entry.fileName)) {
++implementorsCount;
}
});
}
else {
implementorsCount = implementors.length;
}
if (implementorsCount !== count) {
var condition = localFilesOnly ? "excluding libs" : "including libs";
this.raiseError("Expected implementors count (" + condition + ") to be " + count + ", but is actually " + implementors.length);
}
}
private getMemberListAtCaret() {
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, true);
}
@ -787,10 +765,6 @@ module FourSlash {
return this.languageService.getReferencesAtPosition(this.activeFile.fileName, this.currentCaretPosition);
}
private getImplementorsAtCaret() {
return this.languageService.getImplementorsAtPosition(this.activeFile.fileName, this.currentCaretPosition);
}
private assertionMessage(name: string, actualValue: any, expectedValue: any) {
return "\nActual " + name + ":\n\t" + actualValue + "\nExpected value:\n\t" + expectedValue;
}
@ -1017,7 +991,7 @@ module FourSlash {
private alignmentForExtraInfo = 50;
private spanInfoToString(pos: number, spanInfo: TypeScript.TextSpan, prefixString: string) {
private spanInfoToString(pos: number, spanInfo: ts.TextSpan, prefixString: string) {
var resultString = "SpanInfo: " + JSON.stringify(spanInfo);
if (spanInfo) {
var spanString = this.activeFile.content.substr(spanInfo.start(), spanInfo.length());
@ -1034,7 +1008,7 @@ module FourSlash {
return resultString;
}
private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => TypeScript.TextSpan): string {
private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => ts.TextSpan): string {
var fileLineMap = ts.computeLineStarts(this.activeFile.content);
var nextLine = 0;
var resultString = "";
@ -1748,14 +1722,14 @@ module FourSlash {
public verifySemanticClassifications(expected: { classificationType: string; text: string }[]) {
var actual = this.languageService.getSemanticClassifications(this.activeFile.fileName,
new TypeScript.TextSpan(0, this.activeFile.content.length));
new ts.TextSpan(0, this.activeFile.content.length));
this.verifyClassifications(expected, actual);
}
public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) {
var actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName,
new TypeScript.TextSpan(0, this.activeFile.content.length));
new ts.TextSpan(0, this.activeFile.content.length));
this.verifyClassifications(expected, actual);
}
@ -1789,7 +1763,7 @@ module FourSlash {
for (var i = 0; i < spans.length; i++) {
var expectedSpan = spans[i];
var actualComment = actual[i];
var actualCommentSpan = new TypeScript.TextSpan(actualComment.position, actualComment.message.length);
var actualCommentSpan = new ts.TextSpan(actualComment.position, actualComment.message.length);
if (expectedSpan.start !== actualCommentSpan.start() || expectedSpan.end !== actualCommentSpan.end()) {
this.raiseError('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualCommentSpan.start() + ',' + actualCommentSpan.end() + ')');
@ -2240,11 +2214,12 @@ module FourSlash {
(fn, contents) => result = contents,
ts.ScriptTarget.Latest,
sys.useCaseSensitiveFileNames);
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js" }, host);
// TODO (drosen): We need to enforce checking on these tests.
var program = ts.createProgram([Harness.Compiler.fourslashFilename, fileName], { out: "fourslashTestOutput.js", noResolve: true }, host);
var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
checker.checkProgram();
var errs = checker.getDiagnostics(program.getSourceFile(fileName));
var errs = program.getDiagnostics().concat(checker.getDiagnostics());
if (errs.length > 0) {
throw new Error('Error compiling ' + fileName + ': ' + errs.map(e => e.messageText).join('\r\n'));
}
@ -2282,7 +2257,7 @@ module FourSlash {
// List of all the subfiles we've parsed out
var files: FourSlashFile[] = [];
// Global options
var opts: { [s: string]: string; } = {};
var globalOptions: { [s: string]: string; } = {};
// Marker positions
// Split up the input file by line
@ -2290,7 +2265,7 @@ module FourSlash {
// we have to string-based splitting instead and try to figure out the delimiting chars
var lines = contents.split('\n');
var markerMap: MarkerMap = {};
var markerPositions: MarkerMap = {};
var markers: Marker[] = [];
var ranges: Range[] = [];
@ -2331,7 +2306,7 @@ module FourSlash {
} else if (fileMetadataNamesIndex === fileMetadataNames.indexOf(testOptMetadataNames.filename)) {
// Found an @Filename directive, if this is not the first then create a new subfile
if (currentFileContent) {
var file = parseFileContent(currentFileContent, currentFileName, markerMap, markers, ranges);
var file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges);
file.fileOptions = currentFileOptions;
// Store result file
@ -2351,10 +2326,10 @@ module FourSlash {
}
} else {
// Check if the match is already existed in the global options
if (opts[match[1]] !== undefined) {
if (globalOptions[match[1]] !== undefined) {
throw new Error("Global Option : '" + match[1] + "' is already existed");
}
opts[match[1]] = match[2];
globalOptions[match[1]] = match[2];
}
}
} else if (line == '' || lineLength === 0) {
@ -2363,7 +2338,7 @@ module FourSlash {
} else {
// Empty line or code line, terminate current subfile if there is one
if (currentFileContent) {
var file = parseFileContent(currentFileContent, currentFileName, markerMap, markers, ranges);
var file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges);
file.fileOptions = currentFileOptions;
// Store result file
@ -2378,11 +2353,11 @@ module FourSlash {
}
return {
markerPositions: markerMap,
markers: markers,
globalOptions: opts,
files: files,
ranges: ranges
markerPositions,
markers,
globalOptions,
files,
ranges
};
}

View File

@ -587,12 +587,12 @@ module Harness {
return languageVersion === ts.ScriptTarget.ES6 ? defaultES6LibSourceFile : defaultLibSourceFile;
}
// Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC
return null;
return undefined;
}
},
getDefaultLibFilename: (options) => defaultLibFileName,
writeFile: writeFile,
getCanonicalFileName: getCanonicalFileName,
getDefaultLibFilename: options => defaultLibFileName,
writeFile,
getCanonicalFileName,
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
getNewLine: ()=> sys.newLine
};
@ -812,7 +812,7 @@ module Harness {
}
var errors: HarnessDiagnostic[] = [];
program.getDiagnostics().concat(checker.getDiagnostics()).concat(emitResult ? emitResult.errors : []).forEach(err => {
program.getDiagnostics().concat(checker.getDiagnostics()).concat(emitResult ? emitResult.diagnostics : []).forEach(err => {
// TODO: new compiler formats errors after this point to add . and newlines so we'll just do it manually for now
errors.push(getMinimalDiagnostic(err));
});
@ -847,7 +847,7 @@ module Harness {
declResult = compileResult;
}, settingsCallback, options);
return { declInputFiles: declInputFiles, declOtherFiles: declOtherFiles, declResult: declResult };
return { declInputFiles, declOtherFiles, declResult };
}
function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
@ -868,7 +868,7 @@ module Harness {
var sourceFileName: string;
if (ts.isExternalModule(sourceFile) || !options.out) {
if (options.outDir) {
var sourceFilePath = ts.getNormalizedPathFromPathComponents(ts.getNormalizedPathComponents(sourceFile.filename, result.currentDirectoryForProgram));
var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.filename, result.currentDirectoryForProgram);
sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
}
@ -1157,7 +1157,7 @@ module Harness {
var settings = extractCompilerSettings(code);
// List of all the subfiles we've parsed out
var files: TestUnitData[] = [];
var testUnitData: TestUnitData[] = [];
var lines = Utils.splitContentByNewlines(code);
@ -1193,7 +1193,7 @@ module Harness {
originalFilePath: fileName,
references: refs
};
files.push(newTestFile);
testUnitData.push(newTestFile);
// Reset local data
currentFileContent = null;
@ -1218,7 +1218,7 @@ module Harness {
}
// normalize the fileName for the single file case
currentFileName = files.length > 0 ? currentFileName : Path.getFileName(fileName);
currentFileName = testUnitData.length > 0 ? currentFileName : Path.getFileName(fileName);
// EOF, push whatever remains
var newTestFile2 = {
@ -1228,9 +1228,9 @@ module Harness {
originalFilePath: fileName,
references: refs
};
files.push(newTestFile2);
testUnitData.push(newTestFile2);
return { settings: settings, testUnitData: files };
return { settings, testUnitData };
}
}
@ -1326,7 +1326,7 @@ module Harness {
actual = actual.replace(/\r\n?/g, '\n');
}
return { expected: expected, actual: actual };
return { expected, actual };
}
function writeComparison(expected: string, actual: string, relativeFilename: string, actualFilename: string, descriptionForDescribe: string) {

View File

@ -4,8 +4,8 @@
module Harness.LanguageService {
export class ScriptInfo {
public version: number = 1;
public editRanges: { length: number; textChangeRange: TypeScript.TextChangeRange; }[] = [];
public lineMap: TypeScript.LineMap = null;
public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = [];
public lineMap: number[] = null;
constructor(public fileName: string, public content: string, public isOpen = true) {
this.setContent(content);
@ -13,7 +13,7 @@ module Harness.LanguageService {
private setContent(content: string): void {
this.content = content;
this.lineMap = TypeScript.LineMap1.fromString(content);
this.lineMap = ts.computeLineStarts(content);
}
public updateContent(content: string): void {
@ -32,30 +32,30 @@ module Harness.LanguageService {
// Store edit range + new length of script
this.editRanges.push({
length: this.content.length,
textChangeRange: new TypeScript.TextChangeRange(
TypeScript.TextSpan.fromBounds(minChar, limChar), newText.length)
textChangeRange: new ts.TextChangeRange(
ts.TextSpan.fromBounds(minChar, limChar), newText.length)
});
// Update version #
this.version++;
}
public getTextChangeRangeBetweenVersions(startVersion: number, endVersion: number): TypeScript.TextChangeRange {
public getTextChangeRangeBetweenVersions(startVersion: number, endVersion: number): ts.TextChangeRange {
if (startVersion === endVersion) {
// No edits!
return TypeScript.TextChangeRange.unchanged;
return ts.TextChangeRange.unchanged;
}
var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);
var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
return TypeScript.TextChangeRange.collapseChangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
return ts.TextChangeRange.collapseChangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
}
}
class ScriptSnapshotShim implements ts.ScriptSnapshotShim {
private lineMap: TypeScript.LineMap = null;
private lineMap: number[] = null;
private textSnapshot: string;
private version: number;
@ -74,10 +74,10 @@ module Harness.LanguageService {
public getLineStartPositions(): string {
if (this.lineMap === null) {
this.lineMap = TypeScript.LineMap1.fromString(this.textSnapshot);
this.lineMap = ts.computeLineStarts(this.textSnapshot);
}
return JSON.stringify(this.lineMap.lineStarts());
return JSON.stringify(this.lineMap);
}
public getChangeRange(oldScript: ts.ScriptSnapshotShim): string {
@ -108,7 +108,7 @@ module Harness.LanguageService {
public acquireDocument(
fileName: string,
compilationSettings: ts.CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
scriptSnapshot: ts.IScriptSnapshot,
version: string,
isOpen: boolean): ts.SourceFile {
return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, version, isOpen);
@ -118,10 +118,10 @@ module Harness.LanguageService {
document: ts.SourceFile,
fileName: string,
compilationSettings: ts.CompilerOptions,
scriptSnapshot: TypeScript.IScriptSnapshot,
scriptSnapshot: ts.IScriptSnapshot,
version: string,
isOpen: boolean,
textChangeRange: TypeScript.TextChangeRange
textChangeRange: ts.TextChangeRange
): ts.SourceFile {
return document.update(scriptSnapshot, version, isOpen, textChangeRange);
}
@ -263,13 +263,13 @@ module Harness.LanguageService {
}
/** Parse file given its source text */
public parseSourceText(fileName: string, sourceText: TypeScript.IScriptSnapshot): TypeScript.SourceUnitSyntax {
return TypeScript.Parser.parse(fileName, TypeScript.SimpleText.fromScriptSnapshot(sourceText), ts.ScriptTarget.Latest, TypeScript.isDTSFile(fileName)).sourceUnit();
public parseSourceText(fileName: string, sourceText: ts.IScriptSnapshot): ts.SourceFile {
return ts.createSourceFile(fileName, sourceText.getText(0, sourceText.getLength()), ts.ScriptTarget.Latest, "1", true);
}
/** Parse a file on disk given its fileName */
public parseFile(fileName: string) {
var sourceText = TypeScript.ScriptSnapshot.fromString(Harness.IO.readFile(fileName));
var sourceText = ts.ScriptSnapshot.fromString(Harness.IO.readFile(fileName));
return this.parseSourceText(fileName, sourceText);
}
@ -283,22 +283,22 @@ module Harness.LanguageService {
assert.isTrue(line >= 1);
assert.isTrue(col >= 1);
return script.lineMap.getPosition(line - 1, col - 1);
return ts.getPositionFromLineAndCharacter(script.lineMap, line, col);
}
/**
* @param line 0 based index
* @param col 0 based index
*/
public positionToZeroBasedLineCol(fileName: string, position: number): TypeScript.ILineAndCharacter {
public positionToZeroBasedLineCol(fileName: string, position: number): ts.LineAndCharacter {
var script: ScriptInfo = this.fileNameToScript[fileName];
assert.isNotNull(script);
var result = script.lineMap.getLineAndCharacterFromPosition(position);
var result = ts.getLineAndCharacterOfPosition(script.lineMap, position);
assert.isTrue(result.line() >= 0);
assert.isTrue(result.character() >= 0);
return { line: result.line(), character: result.character() };
assert.isTrue(result.line >= 1);
assert.isTrue(result.character >= 1);
return { line: result.line - 1, character: result.character - 1 };
}
/** Verify that applying edits to sourceFileName result in the content of the file baselineFileName */

View File

@ -17,6 +17,7 @@ interface ProjectRunnerTestCase {
baselineCheck?: boolean; // Verify the baselines of output files, if this is false, we will write to output to the disk but there is no verification of baselines
runTest?: boolean; // Run the resulting test
bug?: string; // If there is any bug associated with this test case
noResolve?: boolean;
}
interface ProjectRunnerTestCaseResolutionInfo extends ProjectRunnerTestCase {
@ -132,7 +133,7 @@ class ProjectRunner extends RunnerBase {
var checker = program.getTypeChecker(/*fullTypeCheck*/ true);
errors = checker.getDiagnostics();
var emitResult = checker.emitFiles();
errors = ts.concatenate(errors, emitResult.errors);
errors = ts.concatenate(errors, emitResult.diagnostics);
sourceMapData = emitResult.sourceMaps;
// Clean up source map data that will be used in baselining
@ -148,10 +149,10 @@ class ProjectRunner extends RunnerBase {
}
return {
moduleKind: moduleKind,
program: program,
errors: errors,
sourceMapData: sourceMapData
moduleKind,
program,
errors,
sourceMapData
};
function createCompilerOptions(): ts.CompilerOptions {
@ -162,7 +163,8 @@ class ProjectRunner extends RunnerBase {
outDir: testCase.outDir,
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? sys.resolvePath(testCase.mapRoot) : testCase.mapRoot,
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? sys.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
module: moduleKind
module: moduleKind,
noResolve: testCase.noResolve
};
}
@ -183,10 +185,10 @@ class ProjectRunner extends RunnerBase {
function createCompilerHost(): ts.CompilerHost {
return {
getSourceFile: getSourceFile,
getSourceFile,
getDefaultLibFilename: options => options.target === ts.ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts",
writeFile: writeFile,
getCurrentDirectory: getCurrentDirectory,
writeFile,
getCurrentDirectory,
getCanonicalFileName: Harness.Compiler.getCanonicalFileName,
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames,
getNewLine: () => sys.newLine
@ -201,12 +203,12 @@ class ProjectRunner extends RunnerBase {
var projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile);
return {
moduleKind: moduleKind,
moduleKind,
program: projectCompilerResult.program,
sourceMapData: projectCompilerResult.sourceMapData,
outputFiles: outputFiles,
outputFiles,
errors: projectCompilerResult.errors,
nonSubfolderDiskFiles: nonSubfolderDiskFiles,
nonSubfolderDiskFiles,
};
function getSourceFileText(filename: string): string {
@ -272,16 +274,40 @@ class ProjectRunner extends RunnerBase {
}
function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) {
var inputDtsSourceFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(),
sourceFile => Harness.Compiler.isDTS(sourceFile.filename)),
sourceFile => {
return { emittedFileName: sourceFile.filename, code: sourceFile.text };
});
var allInputFiles: { emittedFileName: string; code: string; }[] = [];
var compilerOptions = compilerResult.program.getCompilerOptions();
var compilerHost = compilerResult.program.getCompilerHost();
ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => {
if (Harness.Compiler.isDTS(sourceFile.filename)) {
allInputFiles.unshift({ emittedFileName: sourceFile.filename, code: sourceFile.text });
}
else if (ts.shouldEmitToOwnFile(sourceFile, compilerResult.program.getCompilerOptions())) {
if (compilerOptions.outDir) {
var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.filename, compilerHost.getCurrentDirectory());
sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), "");
var emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath));
}
else {
var emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.filename);
}
var outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts";
allInputFiles.unshift(findOutpuDtsFile(outputDtsFileName));
}
else {
var outputDtsFileName = ts.removeFileExtension(compilerOptions.out) + ".d.ts";
var outputDtsFile = findOutpuDtsFile(outputDtsFileName);
if (!ts.contains(allInputFiles, outputDtsFile)) {
allInputFiles.unshift(outputDtsFile);
}
}
});
var ouputDtsFiles = ts.filter(compilerResult.outputFiles, ouputFile => Harness.Compiler.isDTS(ouputFile.emittedFileName));
var allInputFiles = inputDtsSourceFiles.concat(ouputDtsFiles);
return compileProjectFiles(compilerResult.moduleKind,getInputFiles, getSourceFileText, writeFile);
function findOutpuDtsFile(fileName: string) {
return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined);
}
function getInputFiles() {
return ts.map(allInputFiles, outputFile => outputFile.emittedFileName);
}

View File

@ -117,14 +117,14 @@ module RWC {
});
function getHarnessCompilerInputUnit(fileName: string) {
var resolvedPath = ts.normalizeSlashes(sys.resolvePath(fileName));
var unitName = ts.normalizeSlashes(sys.resolvePath(fileName));
try {
var content = sys.readFile(resolvedPath);
var content = sys.readFile(unitName);
}
catch (e) {
// Leave content undefined.
}
return { unitName: resolvedPath, content: content };
return { unitName, content };
}
});

View File

@ -38,25 +38,25 @@ module ts.BreakpointResolver {
return spanInNode(tokenAtLocation);
function textSpan(startNode: Node, endNode?: Node) {
return TypeScript.TextSpan.fromBounds(startNode.getStart(), (endNode || startNode).getEnd());
return TextSpan.fromBounds(startNode.getStart(), (endNode || startNode).getEnd());
}
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TypeScript.TextSpan {
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
if (node && lineOfPosition === sourceFile.getLineAndCharacterFromPosition(node.getStart()).line) {
return spanInNode(node);
}
return spanInNode(otherwiseOnNode);
}
function spanInPreviousNode(node: Node): TypeScript.TextSpan {
function spanInPreviousNode(node: Node): TextSpan {
return spanInNode(findPrecedingToken(node.pos, sourceFile));
}
function spanInNextNode(node: Node): TypeScript.TextSpan {
function spanInNextNode(node: Node): TextSpan {
return spanInNode(findNextToken(node, node.parent));
}
function spanInNode(node: Node): TypeScript.TextSpan {
function spanInNode(node: Node): TextSpan {
if (node) {
if (isExpression(node)) {
if (node.parent.kind === SyntaxKind.DoStatement) {
@ -256,7 +256,7 @@ module ts.BreakpointResolver {
}
}
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TypeScript.TextSpan {
function spanInVariableDeclaration(variableDeclaration: VariableDeclaration): TextSpan {
// If declaration of for in statement, just set the span in parent
if (variableDeclaration.parent.kind === SyntaxKind.ForInStatement) {
return spanInNode(variableDeclaration.parent);
@ -301,7 +301,7 @@ module ts.BreakpointResolver {
!!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private);
}
function spanInParameterDeclaration(parameter: ParameterDeclaration): TypeScript.TextSpan {
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
if (canHaveSpanInParameterDeclaration(parameter)) {
return textSpan(parameter);
}
@ -324,7 +324,7 @@ module ts.BreakpointResolver {
(functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
}
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TypeScript.TextSpan {
function spanInFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration): TextSpan {
// No breakpoints in the function signature
if (!functionDeclaration.body) {
return undefined;
@ -339,7 +339,7 @@ module ts.BreakpointResolver {
return spanInNode(functionDeclaration.body);
}
function spanInFunctionBlock(block: Block): TypeScript.TextSpan {
function spanInFunctionBlock(block: Block): TextSpan {
var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
if (canFunctionHaveSpanInWholeDeclaration(<FunctionLikeDeclaration>block.parent)) {
return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
@ -348,7 +348,7 @@ module ts.BreakpointResolver {
return spanInNode(nodeForSpanInBlock);
}
function spanInBlock(block: Block): TypeScript.TextSpan {
function spanInBlock(block: Block): TextSpan {
switch (block.parent.kind) {
case SyntaxKind.ModuleDeclaration:
if (getModuleInstanceState(block.parent) !== ModuleInstanceState.Instantiated) {
@ -370,7 +370,7 @@ module ts.BreakpointResolver {
return spanInNode(block.statements[0]);
}
function spanInForStatement(forStatement: ForStatement): TypeScript.TextSpan {
function spanInForStatement(forStatement: ForStatement): TextSpan {
if (forStatement.declarations) {
return spanInNode(forStatement.declarations[0]);
}
@ -386,7 +386,7 @@ module ts.BreakpointResolver {
}
// Tokens:
function spanInOpenBraceToken(node: Node): TypeScript.TextSpan {
function spanInOpenBraceToken(node: Node): TextSpan {
switch (node.parent.kind) {
case SyntaxKind.EnumDeclaration:
var enumDeclaration = <EnumDeclaration>node.parent;
@ -404,7 +404,7 @@ module ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInCloseBraceToken(node: Node): TypeScript.TextSpan {
function spanInCloseBraceToken(node: Node): TextSpan {
switch (node.parent.kind) {
case SyntaxKind.ModuleBlock:
// If this is not instantiated module block no bp span
@ -439,7 +439,7 @@ module ts.BreakpointResolver {
}
}
function spanInOpenParenToken(node: Node): TypeScript.TextSpan {
function spanInOpenParenToken(node: Node): TextSpan {
if (node.parent.kind === SyntaxKind.DoStatement) {
// Go to while keyword and do action instead
return spanInPreviousNode(node);
@ -449,7 +449,7 @@ module ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInCloseParenToken(node: Node): TypeScript.TextSpan {
function spanInCloseParenToken(node: Node): TextSpan {
// Is this close paren token of parameter list, set span in previous token
switch (node.parent.kind) {
case SyntaxKind.FunctionExpression:
@ -473,7 +473,7 @@ module ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInColonToken(node: Node): TypeScript.TextSpan {
function spanInColonToken(node: Node): TextSpan {
// Is this : specifying return annotation of the function declaration
if (isAnyFunction(node.parent) || node.parent.kind === SyntaxKind.PropertyAssignment) {
return spanInPreviousNode(node);
@ -482,7 +482,7 @@ module ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInGreaterThanOrLessThanToken(node: Node): TypeScript.TextSpan {
function spanInGreaterThanOrLessThanToken(node: Node): TextSpan {
if (node.parent.kind === SyntaxKind.TypeAssertion) {
return spanInNode((<TypeAssertion>node.parent).operand);
}
@ -490,7 +490,7 @@ module ts.BreakpointResolver {
return spanInNode(node.parent);
}
function spanInWhileKeyword(node: Node): TypeScript.TextSpan {
function spanInWhileKeyword(node: Node): TextSpan {
if (node.parent.kind === SyntaxKind.DoStatement) {
// Set span on while expression
return textSpan(node, findNextToken((<DoStatement>node.parent).expression, node.parent));

View File

@ -252,7 +252,7 @@ module ts.formatting {
rulesProvider: RulesProvider,
requestKind: FormattingRequestKind): TextChange[] {
var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.syntacticErrors, originalRange);
var rangeContainsError = prepareRangeContainsErrorFunction(sourceFile.getSyntacticDiagnostics(), originalRange);
// formatting context is used by rules provider
var formattingContext = new FormattingContext(sourceFile, requestKind);
@ -361,8 +361,8 @@ module ts.formatting {
delta = Math.min(options.IndentSize, parentDynamicIndentation.getDelta() + delta);
}
return {
indentation: indentation,
delta: delta
indentation,
delta
}
}
@ -834,7 +834,7 @@ module ts.formatting {
}
function newTextChange(start: number, len: number, newText: string): TextChange {
return { span: new TypeScript.TextSpan(start, len), newText: newText }
return { span: new TextSpan(start, len), newText }
}
function recordDelete(start: number, len: number) {

View File

@ -13,6 +13,7 @@
// limitations under the License.
//
///<reference path='..\text.ts' />
///<reference path='..\services.ts' />
///<reference path='formattingContext.ts' />
///<reference path='formattingRequestKind.ts' />

View File

@ -24,7 +24,7 @@ module ts.formatting {
return name;
}
}
throw new Error(TypeScript.getDiagnosticMessage(TypeScript.DiagnosticCode.Unknown_rule, null));
throw new Error("Unknown rule");
}
[name: string]: any;

View File

@ -22,7 +22,7 @@ module ts.formatting {
private activeRules: Rule[];
private rulesMap: RulesMap;
constructor(private logger: TypeScript.Logger) {
constructor(private logger: Logger) {
this.globalRules = new Rules();
}

View File

@ -16,7 +16,7 @@
///<reference path='references.ts' />
module ts.formatting {
export class TokenSpan extends TypeScript.TextSpan {
export class TokenSpan extends TextSpan {
constructor(public kind: SyntaxKind, start: number, length: number) {
super(start, length);
}

View File

@ -1,5 +1,4 @@
/// <reference path='services.ts' />
/// <reference path="text/textSpan.ts" />
module ts.NavigationBar {
export function getNavigationBarItems(sourceFile: SourceFile): ts.NavigationBarItem[] {
@ -235,8 +234,11 @@ module ts.NavigationBar {
return createItem(node, getTextOfNode((<FunctionLikeDeclaration>node).name), ts.ScriptElementKind.functionElement);
case SyntaxKind.VariableDeclaration:
if (node.flags & NodeFlags.Const) {
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.constantElement);
if (isConst(node)) {
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.constElement);
}
else if (isLet(node)) {
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.letElement);
}
else {
return createItem(node, getTextOfNode((<VariableDeclaration>node).name), ts.ScriptElementKind.variableElement);
@ -257,18 +259,18 @@ module ts.NavigationBar {
return !text || text.trim() === "";
}
function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TypeScript.TextSpan[], childItems: ts.NavigationBarItem[] = [], indent: number = 0): ts.NavigationBarItem {
function getNavigationBarItem(text: string, kind: string, kindModifiers: string, spans: TextSpan[], childItems: NavigationBarItem[] = [], indent: number = 0): NavigationBarItem {
if (isEmpty(text)) {
return undefined;
}
return {
text: text,
kind: kind,
kindModifiers: kindModifiers,
spans: spans,
childItems: childItems,
indent: indent,
text,
kind,
kindModifiers,
spans,
childItems,
indent,
bolded: false,
grayed: false
};
@ -424,8 +426,8 @@ module ts.NavigationBar {
function getNodeSpan(node: Node) {
return node.kind === SyntaxKind.SourceFile
? TypeScript.TextSpan.fromBounds(node.getFullStart(), node.getEnd())
: TypeScript.TextSpan.fromBounds(node.getStart(), node.getEnd());
? TextSpan.fromBounds(node.getFullStart(), node.getEnd())
: TextSpan.fromBounds(node.getStart(), node.getEnd());
}
function getTextOfNode(node: Node): string {

View File

@ -24,8 +24,8 @@ module ts {
* @param autoCollapse Whether or not this region should be automatically collapsed when
* the 'Collapse to Definitions' command is invoked.
*/
textSpan: TypeScript.TextSpan;
hintSpan: TypeScript.TextSpan;
textSpan: TextSpan;
hintSpan: TextSpan;
bannerText: string;
autoCollapse: boolean;
}
@ -38,8 +38,8 @@ module ts {
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean) {
if (hintSpanNode && startElement && endElement) {
var span: OutliningSpan = {
textSpan: TypeScript.TextSpan.fromBounds(startElement.pos, endElement.end),
hintSpan: TypeScript.TextSpan.fromBounds(hintSpanNode.getStart(), hintSpanNode.end),
textSpan: TextSpan.fromBounds(startElement.pos, endElement.end),
hintSpan: TextSpan.fromBounds(hintSpanNode.getStart(), hintSpanNode.end),
bannerText: collapseText,
autoCollapse: autoCollapse
};
@ -86,7 +86,7 @@ module ts {
else {
// Block was a standalone block. In this case we want to only collapse
// the span of the block, independent of any parent span.
var span = TypeScript.TextSpan.fromBounds(n.getStart(), n.end);
var span = TextSpan.fromBounds(n.getStart(), n.end);
elements.push({
textSpan: span,
hintSpan: span,

View File

@ -5,7 +5,7 @@ module TypeScript {
warning_TS_0_1: "warning TS{0}: {1}",
Unrecognized_escape_sequence: "Unrecognized escape sequence.",
Unexpected_character_0: "Unexpected character {0}.",
Missing_close_quote_character: "Missing close quote character.",
Unterminated_string_literal: "Unterminated string literal.",
Identifier_expected: "Identifier expected.",
_0_keyword_expected: "'{0}' keyword expected.",
_0_expected: "'{0}' expected.",
@ -97,6 +97,8 @@ module TypeScript {
Template_literal_cannot_be_used_as_an_element_name: "Template literal cannot be used as an element name.",
Computed_property_names_cannot_be_used_here: "Computed property names cannot be used here.",
yield_expression_must_be_contained_within_a_generator_declaration: "'yield' expression must be contained within a generator declaration.",
Unterminated_regular_expression_literal: "Unterminated regular expression literal.",
Unterminated_template_literal: "Unterminated template literal.",
Duplicate_identifier_0: "Duplicate identifier '{0}'.",
The_name_0_does_not_exist_in_the_current_scope: "The name '{0}' does not exist in the current scope.",
The_name_0_does_not_refer_to_a_value: "The name '{0}' does not refer to a value.",

View File

@ -6,7 +6,7 @@ module TypeScript {
"warning TS{0}: {1}": { "code": 1, "category": DiagnosticCategory.NoPrefix },
"Unrecognized escape sequence.": { "code": 1000, "category": DiagnosticCategory.Error },
"Unexpected character {0}.": { "code": 1001, "category": DiagnosticCategory.Error },
"Missing close quote character.": { "code": 1002, "category": DiagnosticCategory.Error },
"Unterminated string literal.": { "code": 1002, "category": DiagnosticCategory.Error },
"Identifier expected.": { "code": 1003, "category": DiagnosticCategory.Error },
"'{0}' keyword expected.": { "code": 1004, "category": DiagnosticCategory.Error },
"'{0}' expected.": { "code": 1005, "category": DiagnosticCategory.Error },
@ -99,6 +99,8 @@ module TypeScript {
"Template literal cannot be used as an element name.": { "code": 1111, "category": DiagnosticCategory.Error },
"Computed property names cannot be used here.": { "code": 1112, "category": DiagnosticCategory.Error },
"'yield' expression must be contained within a generator declaration.": { "code": 1113, "category": DiagnosticCategory.Error },
"Unterminated regular expression literal.": { "code": 1114, "category": DiagnosticCategory.Error },
"Unterminated template literal.": { "code": 1115, "category": DiagnosticCategory.Error },
"Duplicate identifier '{0}'.": { "code": 2000, "category": DiagnosticCategory.Error },
"The name '{0}' does not exist in the current scope.": { "code": 2001, "category": DiagnosticCategory.Error },
"The name '{0}' does not refer to a value.": { "code": 2002, "category": DiagnosticCategory.Error },

View File

@ -15,7 +15,7 @@
"category": "Error",
"code": 1001
},
"Missing close quote character.": {
"Unterminated string literal.": {
"category": "Error",
"code": 1002
},
@ -383,6 +383,14 @@
"category": "Error",
"code": 1113
},
"Unterminated regular expression literal.": {
"category": "Error",
"code": 1114
},
"Unterminated template literal.": {
"category": "Error",
"code": 1115
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2000

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,6 @@
/// <reference path='services.ts' />
/// <reference path='compiler\pathUtils.ts' />
var debugObjectHost = (<any>this);
module ts {
@ -100,9 +98,6 @@ module ts {
getSignatureHelpItems(fileName: string, position: number): string;
// Obsolete. Use getSignatureHelpItems instead.
getSignatureAtPosition(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
* { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
@ -135,12 +130,6 @@ module ts {
*/
getOccurrencesAtPosition(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[]
*/
getImplementorsAtPosition(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
* { name: string; kind: string; kindModifiers: string; containerName: string; containerKind: string; matchKind: string; fileName: string; textSpan: { start: number; length: number}; } [] = [];
@ -172,11 +161,11 @@ module ts {
}
export interface ClassifierShim extends Shim {
getClassificationsForLine(text: string, lexState: EndOfLineState): string;
getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string;
}
export interface CoreServicesShim extends Shim {
getPreProcessedFileInfo(fileName: string, sourceText: TypeScript.IScriptSnapshot): string;
getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string;
getDefaultCompilationSettings(): string;
}
@ -309,7 +298,7 @@ module ts {
logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
}
class ScriptSnapshotShimAdapter implements TypeScript.IScriptSnapshot {
class ScriptSnapshotShimAdapter implements IScriptSnapshot {
private lineStartPositions: number[] = null;
constructor(private scriptSnapshotShim: ScriptSnapshotShim) {
@ -331,7 +320,7 @@ module ts {
return this.lineStartPositions;
}
public getChangeRange(oldSnapshot: TypeScript.IScriptSnapshot): TypeScript.TextChangeRange {
public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
var oldSnapshotShim = <ScriptSnapshotShimAdapter>oldSnapshot;
var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
if (encoded == null) {
@ -339,8 +328,8 @@ module ts {
}
var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded);
return new TypeScript.TextChangeRange(
new TypeScript.TextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
return new TextChangeRange(
new TextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
}
}
@ -368,7 +357,7 @@ module ts {
return JSON.parse(encoded);
}
public getScriptSnapshot(fileName: string): TypeScript.IScriptSnapshot {
public getScriptSnapshot(fileName: string): IScriptSnapshot {
return new ScriptSnapshotShimAdapter(this.shimHost.getScriptSnapshot(fileName));
}
@ -521,7 +510,7 @@ module ts {
return this.forwardJSONCall(
"getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")",
() => {
var classifications = this.languageService.getSyntacticClassifications(fileName, new TypeScript.TextSpan(start, length));
var classifications = this.languageService.getSyntacticClassifications(fileName, new TextSpan(start, length));
return classifications;
});
}
@ -530,7 +519,7 @@ module ts {
return this.forwardJSONCall(
"getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")",
() => {
var classifications = this.languageService.getSemanticClassifications(fileName, new TypeScript.TextSpan(start, length));
var classifications = this.languageService.getSemanticClassifications(fileName, new TextSpan(start, length));
return classifications;
});
}
@ -617,14 +606,6 @@ module ts {
});
}
public getSignatureAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getSignatureAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getSignatureAtPosition(fileName, position);
});
}
/// GOTO DEFINITION
/**
@ -698,16 +679,6 @@ module ts {
});
}
/// GET IMPLEMENTORS
public getImplementorsAtPosition(fileName: string, position: number): string {
return this.forwardJSONCall(
"getImplementorsAtPosition('" + fileName + "', " + position + ")",
() => {
return this.languageService.getImplementorsAtPosition(fileName, position);
});
}
/// COMPLETION LISTS
/**
@ -823,8 +794,8 @@ module ts {
}
/// COLORIZATION
public getClassificationsForLine(text: string, lexState: EndOfLineState): string {
var classification = this.classifier.getClassificationsForLine(text, lexState);
public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics?: boolean): string {
var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
var items = classification.entries;
var result = "";
for (var i = 0; i < items.length; i++) {
@ -845,7 +816,7 @@ module ts {
return forwardJSONCall(this.logger, actionDescription, action);
}
public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: TypeScript.IScriptSnapshot): string {
public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string {
return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')",
() => {
@ -938,7 +909,7 @@ module ts {
}
}
throw TypeScript.Errors.invalidOperation();
throw new Error("Invalid operation");
}
}
}

View File

@ -164,6 +164,20 @@ module ts.SignatureHelp {
//}
var emptyArray: any[] = [];
const enum ArgumentListKind {
TypeArguments,
CallArguments,
TaggedTemplateArguments
}
interface ArgumentListInfo {
kind: ArgumentListKind;
invocation: CallLikeExpression;
argumentsSpan: TextSpan;
argumentIndex?: number;
argumentCount: number;
}
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
// Decide whether to show signature help
var startingToken = findTokenOnLeftOfPosition(sourceFile, position);
@ -180,7 +194,7 @@ module ts.SignatureHelp {
return undefined;
}
var call = <CallExpression>argumentInfo.list.parent;
var call = argumentInfo.invocation;
var candidates = <Signature[]>[];
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
cancellationToken.throwIfCancellationRequested();
@ -192,50 +206,195 @@ module ts.SignatureHelp {
return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
/**
* If node is an argument, returns its index in the argument list.
* If not, returns -1.
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
function getImmediatelyContainingArgumentInfo(node: Node): ListItemInfo {
if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) {
return undefined;
}
function getImmediatelyContainingArgumentInfo(node: Node): ArgumentListInfo {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
var callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo#o<T, U>#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken ||
node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
Debug.assert(list !== undefined);
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list),
argumentIndex: 0,
argumentCount: getCommaBasedArgCount(list)
};
}
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<$T, U>($a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo$o<T, U>$(a, b)$ -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T$, U$>(a$, $b$) -> The token is buried inside a list, and should give sig help
var parent = <CallExpression>node.parent;
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
Debug.assert(list !== undefined);
return {
list: list,
listItemIndex: 0
};
}
// 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, non-substitution template, or template tail.
// - 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
var listItemInfo = findListItemInfo(node);
if (listItemInfo) {
var list = listItemInfo.list;
var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
// 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);
// The listItemIndex we got back includes commas. Our goal is to return the index of the proper
// item (not including commas). Here are some examples:
// 1. foo(a, b, c #) -> the listItemIndex is 4, we want to return 2
// 2. foo(a, b, # c) -> listItemIndex is 3, we want to return 2
// 3. foo(#a) -> listItemIndex is 0, we want to return 0
//
// In general, we want to subtract the number of commas before the current index.
// But if we are on a comma, we also want to pretend we are on the argument *following*
// the comma. That amounts to taking the ceiling of half the index.
var argumentIndex = (listItemInfo.listItemIndex + 1) >> 1;
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list),
argumentIndex: argumentIndex,
argumentCount: getCommaBasedArgCount(list)
};
}
}
else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) {
// Check if we're actually inside the template;
// otherwise we'll fall out and return undefined.
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return getArgumentListInfoForTemplate(<TaggedTemplateExpression>node.parent, /*argumentIndex*/ 0);
}
}
else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
var templateExpression = <TemplateExpression>node.parent;
var tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
var argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
}
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
var templateSpan = <TemplateSpan>node.parent;
var templateExpression = <TemplateExpression>templateSpan.parent;
var tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
// If we're just after a template tail, don't show signature help.
if (node.kind === SyntaxKind.TemplateTail && position >= node.getEnd() && !isUnterminatedTemplateEnd(<LiteralExpression>node)) {
return undefined;
}
var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
}
return undefined;
}
function getContainingArgumentInfo(node: Node): ListItemInfo {
function getCommaBasedArgCount(argumentsList: Node) {
// The number of arguments is the number of commas plus one, unless the list
// is completely empty, in which case there are 0 arguments.
return argumentsList.getChildCount() === 0
? 0
: 1 + countWhere(argumentsList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
}
// spanIndex is either the index for a given template span.
// This does not give appropriate results for a NoSubstitutionTemplateLiteral
function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node): number {
// Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
// There are three cases we can encounter:
// 1. We are precisely in the template literal (argIndex = 0).
// 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
// 3. We are directly to the right of the template literal, but because we look for the token on the left,
// not enough to put us in the substitution expression; we should consider ourselves part of
// the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
//
// Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
// ^ ^ ^ ^ ^ ^ ^ ^ ^
// Case: 1 1 3 2 1 3 2 2 1
Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
if (isTemplateLiteralKind(node.kind)) {
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return 0;
}
return spanIndex + 2;
}
return spanIndex + 1;
}
function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number): ArgumentListInfo {
// argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
var argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
? 1
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
return {
kind: ArgumentListKind.TaggedTemplateArguments,
invocation: tagExpression,
argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
function getApplicableSpanForArguments(argumentsList: Node): TextSpan {
// We use full start and skip trivia on the end because we want to include trivia on
// both sides. For example,
//
// foo( /*comment */ a, b, c /*comment*/ )
// | |
//
// The applicable span is from the first bar to the second bar (inclusive,
// but not including parentheses)
var applicableSpanStart = argumentsList.getFullStart();
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
return new TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression): TextSpan {
var template = taggedTemplate.template;
var applicableSpanStart = template.getStart();
var applicableSpanEnd = template.getEnd();
// We need to adjust the end position for the case where the template does not have a tail.
// Otherwise, we will not show signature help past the expression.
// For example,
//
// ` ${ 1 + 1 foo(10)
// | |
//
// This is because a Missing node has no width. However, what we actually want is to include trivia
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
if (template.kind === SyntaxKind.TemplateExpression) {
var lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
if (lastSpan.literal.kind === SyntaxKind.Missing) {
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
}
}
return new TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getContainingArgumentInfo(node: Node): ArgumentListInfo {
for (var n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
if (n.kind === SyntaxKind.FunctionBlock) {
return undefined;
@ -292,85 +451,61 @@ module ts.SignatureHelp {
return maxParamsSignatureIndex;
}
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentInfoOrTypeArgumentInfo: ListItemInfo): SignatureHelpItems {
var argumentListOrTypeArgumentList = argumentInfoOrTypeArgumentInfo.list;
var parent = <CallExpression>argumentListOrTypeArgumentList.parent;
var isTypeParameterHelp = parent.typeArguments && parent.typeArguments.pos === argumentListOrTypeArgumentList.pos;
Debug.assert(isTypeParameterHelp || parent.arguments.pos === argumentListOrTypeArgumentList.pos);
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListInfo: ArgumentListInfo): SignatureHelpItems {
var applicableSpan = argumentListInfo.argumentsSpan;
var isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
var invocation = argumentListInfo.invocation;
var callTarget = getInvokedExpression(invocation)
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTarget);
var callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
var signatureHelpParameters: SignatureHelpParameter[];
var prefixParts: SymbolDisplayPart[] = [];
var suffixParts: SymbolDisplayPart[] = [];
var prefixDisplayParts: SymbolDisplayPart[] = [];
var suffixDisplayParts: SymbolDisplayPart[] = [];
if (callTargetDisplayParts) {
prefixParts.push.apply(prefixParts, callTargetDisplayParts);
prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
}
if (isTypeParameterHelp) {
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
if (isTypeParameterList) {
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
var typeParameters = candidateSignature.typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
var parameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, argumentListOrTypeArgumentList));
suffixParts.push.apply(suffixParts, parameterParts);
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation));
suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
}
else {
var typeParameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, argumentListOrTypeArgumentList));
prefixParts.push.apply(prefixParts, typeParameterParts);
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation));
prefixDisplayParts.push.apply(prefixDisplayParts, typeParameterParts);
prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
var parameters = candidateSignature.parameters;
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
suffixParts.push(punctuationPart(SyntaxKind.CloseParenToken));
suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
var returnTypeParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, argumentListOrTypeArgumentList));
suffixParts.push.apply(suffixParts, returnTypeParts);
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
return {
isVariadic: candidateSignature.hasRestParameter,
prefixDisplayParts: prefixParts,
suffixDisplayParts: suffixParts,
prefixDisplayParts,
suffixDisplayParts,
separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
parameters: signatureHelpParameters,
documentation: candidateSignature.getDocumentationComment()
};
});
// We use full start and skip trivia on the end because we want to include trivia on
// both sides. For example,
//
// foo( /*comment */ a, b, c /*comment*/ )
// | |
//
// The applicable span is from the first bar to the second bar (inclusive,
// but not including parentheses)
var applicableSpanStart = argumentListOrTypeArgumentList.getFullStart();
var applicableSpanEnd = skipTrivia(sourceFile.text, argumentListOrTypeArgumentList.end, /*stopAfterLineBreak*/ false);
var applicableSpan = new TypeScript.TextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
var argumentIndex = argumentListInfo.argumentIndex;
// The listItemIndex we got back includes commas. Our goal is to return the index of the proper
// item (not including commas). Here are some examples:
// 1. foo(a, b, c $) -> the listItemIndex is 4, we want to return 2
// 2. foo(a, b, $ c) -> listItemIndex is 3, we want to return 2
// 3. foo($a) -> listItemIndex is 0, we want to return 0
//
// In general, we want to subtract the number of commas before the current index.
// But if we are on a comma, we also want to pretend we are on the argument *following*
// the comma. That amounts to taking the ceiling of half the index.
var argumentIndex = (argumentInfoOrTypeArgumentInfo.listItemIndex + 1) >> 1;
// argumentCount is the number of commas plus one, unless the list is completely empty,
// in which case there are 0.
var argumentCount = argumentListOrTypeArgumentList.getChildCount() === 0
? 0
: 1 + countWhere(argumentListOrTypeArgumentList.getChildren(), arg => arg.kind === SyntaxKind.CommaToken);
// argumentCount is the *apparent* number of arguments.
var argumentCount = argumentListInfo.argumentCount;
var selectedItemIndex = candidates.indexOf(bestSignature);
if (selectedItemIndex < 0) {
@ -378,35 +513,35 @@ module ts.SignatureHelp {
}
return {
items: items,
applicableSpan: applicableSpan,
selectedItemIndex: selectedItemIndex,
argumentIndex: argumentIndex,
argumentCount: argumentCount
items,
applicableSpan,
selectedItemIndex,
argumentIndex,
argumentCount
};
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
var displayParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, argumentListOrTypeArgumentList));
typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation));
var isOptional = !!(parameter.valueDeclaration.flags & NodeFlags.QuestionMark);
return {
name: parameter.name,
documentation: parameter.getDocumentationComment(),
displayParts: displayParts,
isOptional: isOptional
displayParts,
isOptional
};
}
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
var displayParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, argumentListOrTypeArgumentList));
typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation));
return {
name: typeParameter.symbol.name,
documentation: emptyArray,
displayParts: displayParts,
displayParts,
isOptional: false
};
}

View File

@ -222,7 +222,8 @@ module ts.formatting {
if (node.parent) {
switch (node.parent.kind) {
case SyntaxKind.TypeReference:
if ((<TypeReferenceNode>node.parent).typeArguments) {
if ((<TypeReferenceNode>node.parent).typeArguments &&
rangeContainsStartEnd((<TypeReferenceNode>node.parent).typeArguments, node.getStart(sourceFile), node.getEnd())) {
return (<TypeReferenceNode>node.parent).typeArguments;
}
break;
@ -236,21 +237,28 @@ module ts.formatting {
case SyntaxKind.Method:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
if ((<SignatureDeclaration>node.parent).typeParameters && node.end < (<SignatureDeclaration>node.parent).typeParameters.end) {
var start = node.getStart(sourceFile);
if ((<SignatureDeclaration>node.parent).typeParameters &&
rangeContainsStartEnd((<SignatureDeclaration>node.parent).typeParameters, start, node.getEnd())) {
return (<SignatureDeclaration>node.parent).typeParameters;
}
return (<SignatureDeclaration>node.parent).parameters;
if (rangeContainsStartEnd((<SignatureDeclaration>node.parent).parameters, start, node.getEnd())) {
return (<SignatureDeclaration>node.parent).parameters;
}
break;
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
if ((<CallExpression>node.parent).typeArguments && node.end < (<CallExpression>node.parent).typeArguments.end) {
var start = node.getStart(sourceFile);
if ((<CallExpression>node.parent).typeArguments &&
rangeContainsStartEnd((<CallExpression>node.parent).typeArguments, start, node.getEnd())) {
return (<CallExpression>node.parent).typeArguments;
}
return (<CallExpression>node.parent).arguments;
if (rangeContainsStartEnd((<CallExpression>node.parent).arguments, start, node.getEnd())) {
return (<CallExpression>node.parent).arguments;
}
break;
}
}
return undefined;
}

View File

@ -621,9 +621,10 @@ var TypeScript;
SyntaxKind[SyntaxKind["Parameter"] = 209] = "Parameter";
SyntaxKind[SyntaxKind["EnumElement"] = 210] = "EnumElement";
SyntaxKind[SyntaxKind["TypeAnnotation"] = 211] = "TypeAnnotation";
SyntaxKind[SyntaxKind["ComputedPropertyName"] = 212] = "ComputedPropertyName";
SyntaxKind[SyntaxKind["ExternalModuleReference"] = 213] = "ExternalModuleReference";
SyntaxKind[SyntaxKind["ModuleNameModuleReference"] = 214] = "ModuleNameModuleReference";
SyntaxKind[SyntaxKind["ExpressionBody"] = 212] = "ExpressionBody";
SyntaxKind[SyntaxKind["ComputedPropertyName"] = 213] = "ComputedPropertyName";
SyntaxKind[SyntaxKind["ExternalModuleReference"] = 214] = "ExternalModuleReference";
SyntaxKind[SyntaxKind["ModuleNameModuleReference"] = 215] = "ModuleNameModuleReference";
SyntaxKind[SyntaxKind["FirstStandardKeyword"] = SyntaxKind.BreakKeyword] = "FirstStandardKeyword";
SyntaxKind[SyntaxKind["LastStandardKeyword"] = SyntaxKind.WithKeyword] = "LastStandardKeyword";
SyntaxKind[SyntaxKind["FirstFutureReservedKeyword"] = SyntaxKind.ClassKeyword] = "FirstFutureReservedKeyword";
@ -1016,7 +1017,15 @@ var definitions = [
{ name: 'asterixToken', isToken: true, isOptional: true },
{ name: 'identifier', isToken: true },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
{
name: 'ExpressionBody',
baseType: 'ISyntaxNode',
children: [
{ name: 'equalsGreaterThanToken', isToken: true },
{ name: 'expression', type: 'IExpressionSyntax' }
]
},
{
@ -1246,6 +1255,7 @@ var definitions = [
baseType: 'ISyntaxNode',
interfaces: ['IStatementSyntax'],
children: [
{ name: 'equalsGreaterThanToken', isToken: true, isOptional: 'true' },
{ name: 'openBraceToken', isToken: true },
{ name: 'statements', isList: true, elementType: 'IStatementSyntax' },
{ name: 'closeBraceToken', isToken: true, excludeFromAST: true }
@ -1289,7 +1299,7 @@ var definitions = [
children: [
{ name: 'expression', type: 'ILeftHandSideExpressionSyntax' },
{ name: 'openBracketToken', isToken: true, excludeFromAST: true },
{ name: 'argumentExpression', type: 'IExpressionSyntax' },
{ name: 'argumentExpression', type: 'IExpressionSyntax', isOptional: true },
{ name: 'closeBracketToken', isToken: true, excludeFromAST: true }
]
},
@ -1488,7 +1498,7 @@ var definitions = [
{ name: 'modifiers', isList: true, elementType: 'ISyntaxToken' },
{ name: 'constructorKeyword', isToken: true },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -1501,7 +1511,7 @@ var definitions = [
{ name: 'asterixToken', isToken: true, isOptional: true },
{ name: 'propertyName', type: 'IPropertyNameSyntax' },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -1514,7 +1524,7 @@ var definitions = [
{ name: 'getKeyword', isToken: true, excludeFromAST: true },
{ name: 'propertyName', type: 'IPropertyNameSyntax' },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'block', type: 'BlockSyntax' }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
{
@ -1526,7 +1536,7 @@ var definitions = [
{ name: 'setKeyword', isToken: true, excludeFromAST: true },
{ name: 'propertyName', type: 'IPropertyNameSyntax' },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'block', type: 'BlockSyntax' }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -1558,7 +1568,7 @@ var definitions = [
interfaces: ['IStatementSyntax'],
children: [
{ name: 'throwKeyword', isToken: true, excludeFromAST: true },
{ name: 'expression', type: 'IExpressionSyntax' },
{ name: 'expression', type: 'IExpressionSyntax', isOptional: true },
{ name: 'semicolonToken', isToken: true, isOptional: true, excludeFromAST: true }
]
},
@ -1763,7 +1773,7 @@ var definitions = [
{ name: 'asterixToken', isToken: true, isOptional: true },
{ name: 'propertyName', type: 'IPropertyNameSyntax' },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'block', type: 'BlockSyntax' }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
{
@ -1775,7 +1785,7 @@ var definitions = [
{ name: 'asterixToken', isToken: true, isOptional: true },
{ name: 'identifier', isToken: true, isOptional: true },
{ name: 'callSignature', type: 'CallSignatureSyntax' },
{ name: 'block', type: 'BlockSyntax' }
{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
{

File diff suppressed because one or more lines are too long

View File

@ -1,29 +1,24 @@
///<reference path='references.ts' />
module TypeScript {
export const enum ParserContextFlags {
StrictMode = 1 << 0,
DisallowIn = 1 << 1,
Yield = 1 << 2,
GeneratorParameter = 1 << 3,
Mask = 0xF
}
export enum SyntaxNodeConstants {
None = 0,
// Masks that we use to place information about a node into a single int. The first bit tells
// us if we've computed the data for a node.
//
// The second bit tells us if the node is incrementally reusable if it does not
// containe any skipped tokens, zero width tokens, regex tokens in it ("/", "/=" or "/.../"),
// and contains no tokens that were parser generated.
//
// The next bit lets us know if the nodes was parsed in a strict context or node. A node can
// only be used by the incremental parser if it is parsed in the same strict context as before.
// last masks off the part of the int
//
// The first four bit of the flags are used to store parser context flags.
// The width of the node is stored in the remainder of the int. This allows us up to 128MB
// for a node by using all 27 bits. However, in the common case, we'll use less than 27 bits
// for the width. Thus, the info will be stored in a single int in chakra.
DataComputed = 0x00000001, // 0000 0000 0000 0000 0000 0000 0000 0001
IncrementallyUnusableMask = 0x00000002, // 0000 0000 0000 0000 0000 0000 0000 0010
ParsedInStrictModeContext = 0x00000004, // 0000 0000 0000 0000 0000 0000 0000 0100
ParsedInDisallowInContext = 0x00000008, // 0000 0000 0000 0000 0000 0000 0000 1000
ParsedInYieldContext = 0x00000010, // 0000 0000 0000 0000 0000 0000 0001 0000
ParsedInGeneratorParameterContext = 0x00000020, // 0000 0000 0000 0000 0000 0000 0010 0000
FullWidthShift = 1 << 6, // 1111 1111 1111 1111 1111 1111 1100 0000
DataComputed = 1 << 4, // 0000 0000 0000 0000 0000 0000 0001 0000
IncrementallyUnusableMask = 1 << 5, // 0000 0000 0000 0000 0000 0000 0010 0000
FullWidthShift = 1 << 6, // 1111 1111 1111 1111 1111 1111 1100 0000
}
}

View File

@ -4,8 +4,10 @@ module TypeScript.IncrementalParser {
interface IParserRewindPoint {
// Information used by the incremental parser source.
oldSourceUnitCursor: SyntaxCursor;
changeDelta: number;
changeRange: TextChangeRange;
}
interface ISyntaxElementInternal extends ISyntaxElement {
intersectsChange: boolean;
}
// Parser source used in incremental scenarios. This parser source wraps an old tree, text
@ -21,9 +23,6 @@ module TypeScript.IncrementalParser {
// prevent this level of reuse include substantially destructive operations like introducing
// "/*" without a "*/" nearby to terminate the comment.
function createParserSource(oldSyntaxTree: SyntaxTree, textChangeRange: TextChangeRange, text: ISimpleText): Parser.IParserSource {
var fileName = oldSyntaxTree.fileName();
var languageVersion = oldSyntaxTree.languageVersion();
// The underlying source that we will use to scan tokens from any new text, or any tokens
// from the old tree that we decide we can't use for any reason. We will also continue
// scanning tokens from this source until we've decided that we're resynchronized and can
@ -31,40 +30,15 @@ module TypeScript.IncrementalParser {
//
// This parser source also keeps track of the absolute position in the text that we're in,
// and any token diagnostics produced. That way we dont' have to track that ourselves.
var _scannerParserSource: Scanner.IScannerParserSource;
// The range of text in the *original* text that was changed, and the new length of it after
// the change.
var _changeRange: TextChangeRange;
// Cached value of _changeRange.newSpan(). Cached for performance.
var _changeRangeNewSpan: TextSpan;
// This number represents how our position in the old tree relates to the position we're
// pointing at in the new text. If it is 0 then our positions are in sync and we can read
// nodes or tokens from the old tree. If it is non-zero, then our positions are not in
// sync and we cannot use nodes or tokens from the old tree.
//
// Now, changeDelta could be negative or positive. Negative means 'the position we're at
// in the original tree is behind the position we're at in the text'. In this case we
// keep throwing out old nodes or tokens (and thus move forward in the original tree) until
// changeDelta becomes 0 again or positive. If it becomes 0 then we are resynched and can
// read nodes or tokesn from the tree.
//
// If changeDelta is positive, that means the current node or token we're pointing at in
// the old tree is at a further ahead position than the position we're pointing at in the
// new text. In this case we have no choice but to scan tokens from teh new text. We will
// continue to do so until, again, changeDelta becomes 0 and we've resynced, or change delta
// becomes negative and we need to skip nodes or tokes in the original tree.
var _changeDelta: number = 0;
var _scannerParserSource = Scanner.createParserSource(oldSyntaxTree.fileName(), text, oldSyntaxTree.languageVersion());
// The cursor we use to navigate through and retrieve nodes and tokens from the old tree.
var _oldSourceUnitCursor = getSyntaxCursor();
var oldSourceUnit = oldSyntaxTree.sourceUnit();
var _outstandingRewindPointCount = 0;
// Start the cursor pointing at the first element in the source unit (if it exists).
var _oldSourceUnitCursor = getSyntaxCursor();
if (oldSourceUnit.moduleElements.length > 0) {
_oldSourceUnitCursor.pushElement(childAt(oldSourceUnit.moduleElements, 0), /*indexInParent:*/ 0);
}
@ -74,8 +48,10 @@ module TypeScript.IncrementalParser {
// time this could be problematic would be if the user made a ton of discontinuous edits.
// For example, doing a column select on a *large* section of a code. If this is a
// problem, we can always update this code to handle multiple changes.
_changeRange = extendToAffectedRange(textChangeRange, oldSourceUnit);
_changeRangeNewSpan = _changeRange.newSpan();
var _changeRange = extendToAffectedRange(textChangeRange, oldSourceUnit);
// Cached value of _changeRange.newSpan(). Cached for performance.
var _changeRangeNewSpan = _changeRange.newSpan();
// The old tree's length, plus whatever length change was caused by the edit
// Had better equal the new text's length!
@ -83,8 +59,23 @@ module TypeScript.IncrementalParser {
Debug.assert((fullWidth(oldSourceUnit) - _changeRange.span().length() + _changeRange.newLength()) === text.length());
}
// Set up a scanner so that we can scan tokens out of the new text.
_scannerParserSource = Scanner.createParserSource(oldSyntaxTree.fileName(), text, oldSyntaxTree.languageVersion());
var delta = _changeRange.newSpan().length() - _changeRange.span().length();
// If we added or removed characters during the edit, then we need to go and adjust all
// the nodes after the edit. Those nodes may move forward down (if we inserted chars)
// or they may move backward (if we deleted chars).
//
// Doing this helps us out in two ways. First, it means that any nodes/tokens we want
// to reuse are already at the appropriate position in the new text. That way when we
// reuse them, we don't have to figure out if they need to be adjusted. Second, it makes
// it very easy to determine if we can reuse a node. If the node's position is at where
// we are in the text, then we can reuse it. Otherwise we can't. If hte node's position
// is ahead of us, then we'll need to rescan tokens. If the node's position is behind
// us, then we'll need to skip it or crumble it as appropriate
//
// Also, mark any syntax elements that intersect the changed span. We know, up front,
// that we cannot reuse these elements.
updateTokenPositionsAndMarkElements(<ISyntaxElementInternal><ISyntaxElement>oldSourceUnit,
_changeRange.span().start(), _changeRange.span().end(), delta, /*fullStart:*/ 0);
function release() {
_scannerParserSource.release();
@ -93,8 +84,7 @@ module TypeScript.IncrementalParser {
_outstandingRewindPointCount = 0;
}
function extendToAffectedRange(changeRange: TextChangeRange,
sourceUnit: SourceUnitSyntax): TextChangeRange {
function extendToAffectedRange(changeRange: TextChangeRange, sourceUnit: SourceUnitSyntax): TextChangeRange {
// Consider the following code:
// void foo() { /; }
//
@ -105,14 +95,6 @@ module TypeScript.IncrementalParser {
// (as it does not intersect the actual original change range). Because an edit may
// change the token touching it, we actually need to look back *at least* one token so
// that the prior token sees that change.
//
// Note: i believe (outside of regex tokens) max lookahead is just one token for
// TypeScript. However, if this turns out to be wrong, we may have to increase how much
// futher we look back.
//
// Note: lookahead handling for regex characters is handled specially in during
// incremental parsing, and does not need to be handled here.
var maxLookahead = 1;
var start = changeRange.span().start();
@ -122,10 +104,6 @@ module TypeScript.IncrementalParser {
// start of the tree.
for (var i = 0; start > 0 && i <= maxLookahead; i++) {
var token = findToken(sourceUnit, start);
// Debug.assert(token.kind !== SyntaxKind.None);
// Debug.assert(token.kind() === SyntaxKind.EndOfFileToken || token.fullWidth() > 0);
var position = token.fullStart();
start = Math.max(0, position - 1);
@ -149,17 +127,8 @@ module TypeScript.IncrementalParser {
// Get a rewind point for our new text reader and for our old source unit cursor.
var rewindPoint = <IParserRewindPoint>_scannerParserSource.getRewindPoint();
// Clone our cursor. That way we can restore to that point if hte parser needs to rewind.
var oldSourceUnitCursorClone = cloneSyntaxCursor(_oldSourceUnitCursor);
// Store where we were when the rewind point was created.
rewindPoint.changeDelta = _changeDelta;
rewindPoint.changeRange = _changeRange;
rewindPoint.oldSourceUnitCursor = _oldSourceUnitCursor;
_oldSourceUnitCursor = oldSourceUnitCursorClone;
// Debug.assert(rewindPoint.pinCount === _oldSourceUnitCursor.pinCount());
// Clone our cursor. That way we can restore to that point if the parser needs to rewind.
rewindPoint.oldSourceUnitCursor = cloneSyntaxCursor(_oldSourceUnitCursor);
_outstandingRewindPointCount++;
return rewindPoint;
@ -167,15 +136,13 @@ module TypeScript.IncrementalParser {
function rewind(rewindPoint: IParserRewindPoint): void {
// Restore our state to the values when the rewind point was created.
_changeRange = rewindPoint.changeRange;
_changeDelta = rewindPoint.changeDelta;
// Reset the cursor to what it was when we got the rewind point. Make sure to return
// our existing cursor to the pool so it can be reused.
returnSyntaxCursor(_oldSourceUnitCursor);
_oldSourceUnitCursor = rewindPoint.oldSourceUnitCursor;
// Null out the cursor that the rewind point points to. This way we don't try
// Clear the cursor that the rewind point points to. This way we don't try
// to return it in 'releaseRewindPoint'.
rewindPoint.oldSourceUnitCursor = undefined;
@ -196,7 +163,7 @@ module TypeScript.IncrementalParser {
return _outstandingRewindPointCount > 0;
}
function canReadFromOldSourceUnit() {
function trySynchronizeCursorToPosition() {
// If we're currently pinned, then do not want to touch the cursor. Here's why. First,
// recall that we're 'pinned' when we're speculatively parsing. So say we were to allow
// returning old nodes/tokens while speculatively parsing. Then, the parser might start
@ -218,81 +185,72 @@ module TypeScript.IncrementalParser {
return false;
}
// If our current absolute position is in the middle of the changed range in the new text
// then we definitely can't read from the old source unit right now.
if (_changeRange && _changeRangeNewSpan.intersectsWithPosition(absolutePosition())) {
return false;
}
var absolutePos = absolutePosition();
while (true) {
if (_oldSourceUnitCursor.isFinished()) {
// Can't synchronize the cursor to the current position if the cursor is finished.
return false;
}
// First, try to sync up with the new text if we're behind.
syncCursorToNewTextIfBehind();
// Start with the current node or token the cursor is pointing at.
var currentNodeOrToken = _oldSourceUnitCursor.currentNodeOrToken();
// Now, if we're synced up *and* we're not currently pinned in the new text scanner,
// then we can read a node from the cursor. If we're pinned in the scanner then we
// can't read a node from the cursor because we will mess up the pinned scanner when
// we try to move it forward past this node.
return _changeDelta === 0 &&
!_oldSourceUnitCursor.isFinished();
}
// Node, move the cursor past any nodes or tokens that intersect the change range
// 1) they are never reusable.
// 2) their positions are wacky as they refer to the original text.
//
// We consider these nodes and tokens essentially invisible to all further parts
// of the incremental algorithm.
if ((<ISyntaxElementInternal><ISyntaxElement>currentNodeOrToken).intersectsChange) {
if (isNode(currentNodeOrToken)) {
_oldSourceUnitCursor.moveToFirstChild();
}
else {
_oldSourceUnitCursor.moveToNextSibling();
}
continue;
}
function updateTokenPosition(token: ISyntaxToken): void {
// If we got a node or token, and we're past the range of edited text, then walk its
// constituent tokens, making sure all their positions are correct. We don't need to
// do this for the tokens before the edited range (since their positions couldn't have
// been affected by the edit), and we don't need to do this for the tokens in the
// edited range, as their positions will be correct when the underlying parser source
// creates them.
var currentNodeOrTokenFullStart = fullStart(currentNodeOrToken);
if (currentNodeOrTokenFullStart === absolutePos) {
// We were able to synchronize the cursor to the current position. We can
// read from the cursor
return true;
}
if (isPastChangeRange()) {
token.setFullStart(absolutePosition());
}
}
if (currentNodeOrTokenFullStart > absolutePos) {
// The node or token is ahead of the current position. We'll need to rescan
// tokens until we catch up.
return false;
}
function updateNodePosition(node: ISyntaxNode): void {
// If we got a node or token, and we're past the range of edited text, then walk its
// constituent tokens, making sure all their positions are correct. We don't need to
// do this for the tokens before the edited range (since their positions couldn't have
// been affected by the edit), and we don't need to do this for the tokens in the
// edited range, as their positions will be correct when the underlying parser source
// creates them.
// The node or is behind the current position we're at in the text.
if (isPastChangeRange()) {
var position = absolutePosition();
var currentNodeOrTokenFullWidth = fullWidth(currentNodeOrToken);
var currentNodeOrTokenFullEnd = currentNodeOrTokenFullStart + currentNodeOrTokenFullWidth;
var tokens = getTokens(node);
for (var i = 0, n = tokens.length; i < n; i++) {
var token = tokens[i];
token.setFullStart(position);
position += token.fullWidth();
// If we're pointing at a node, and that node ends before our current position, we
// can just skip the node entirely. Or, if we're pointing at a token, we won't be
// able to break up that token any further and we should just move to the next
// token.
if (currentNodeOrTokenFullEnd <= absolutePos || isToken(currentNodeOrToken)) {
_oldSourceUnitCursor.moveToNextSibling();
}
else {
// We have a node, and it started before our absolute pos, and ended after our
// pos. Try to crumble this node to see if we'll be able to skip the first node
// or token contained within.
_oldSourceUnitCursor.moveToFirstChild();
}
}
}
function getTokens(node: ISyntaxNode): ISyntaxToken[] {
var tokens = node.__cachedTokens;
if (!tokens) {
tokens = [];
tokenCollectorWalker.tokens = tokens;
visitNodeOrToken(tokenCollectorWalker, node);
node.__cachedTokens = tokens;
tokenCollectorWalker.tokens = undefined;
}
return tokens;
}
function currentNode(): ISyntaxNode {
if (canReadFromOldSourceUnit()) {
if (trySynchronizeCursorToPosition()) {
// Try to read a node. If we can't then our caller will call back in and just try
// to get a token.
var node = tryGetNodeFromOldSourceUnit();
if (node) {
// Make sure the positions for the tokens in this node are correct.
updateNodePosition(node);
return node;
}
}
@ -302,11 +260,9 @@ module TypeScript.IncrementalParser {
}
function currentToken(): ISyntaxToken {
if (canReadFromOldSourceUnit()) {
if (trySynchronizeCursorToPosition()) {
var token = tryGetTokenFromOldSourceUnit();
if (token) {
// Make sure the token's position/text is correct.
updateTokenPosition(token);
return token;
}
}
@ -321,69 +277,13 @@ module TypeScript.IncrementalParser {
return _scannerParserSource.currentContextualToken();
}
function syncCursorToNewTextIfBehind() {
while (true) {
if (_oldSourceUnitCursor.isFinished()) {
// Can't sync up if the cursor is finished.
break;
}
if (_changeDelta >= 0) {
// Nothing to do if we're synced up or ahead of the text.
break;
}
// We're behind in the original tree. Throw out a node or token in an attempt to
// catch up to the position we're at in the new text.
var currentNodeOrToken = _oldSourceUnitCursor.currentNodeOrToken();
// If we're pointing at a node, and that node's width is less than our delta,
// then we can just skip that node. Otherwise, if we're pointing at a node
// whose width is greater than the delta, then crumble it and try again.
// Otherwise, we must be pointing at a token. Just skip it and try again.
if (isNode(currentNodeOrToken) && (fullWidth(currentNodeOrToken) > Math.abs(_changeDelta))) {
// We were pointing at a node whose width was more than changeDelta. Crumble the
// node and try again. Note: we haven't changed changeDelta. So the callers loop
// will just repeat this until we get to a node or token that we can skip over.
_oldSourceUnitCursor.moveToFirstChild();
}
else {
_oldSourceUnitCursor.moveToNextSibling();
// Get our change delta closer to 0 as we skip past this item.
_changeDelta += fullWidth(currentNodeOrToken);
// If this was a node, then our changeDelta is 0 or negative. If this was a
// token, then we could still be negative (and we have to read another token),
// we could be zero (we're done), or we could be positive (we've moved ahead
// of the new text). Only if we're negative will we continue looping.
}
}
// At this point, we must be either:
// a) done with the cursor
// b) (ideally) caught up to the new text position.
// c) ahead of the new text position.
// In case 'b' we can try to reuse a node from teh old tree.
// Debug.assert(_oldSourceUnitCursor.isFinished() || _changeDelta >= 0);
}
function intersectsWithChangeRangeSpanInOriginalText(start: number, length: number) {
return !isPastChangeRange() && _changeRange.span().intersectsWith(start, length);
}
function tryGetNodeFromOldSourceUnit(): ISyntaxNode {
// Debug.assert(canReadFromOldSourceUnit());
// Keep moving the cursor down to the first node that is safe to return. A node is
// safe to return if:
// a) it does not intersect the changed text.
// b) it does not contain skipped text.
// c) it does not have any zero width tokens in it.
// d) it does not have a regex token in it.
// e) we are still in the same strict or non-strict state that the node was originally parsed in.
// a) it does not contain skipped text.
// b) it does not have any zero width tokens in it.
// c) it does not have a regex token in it.
// d) we are still in the same strict or non-strict state that the node was originally parsed in.
while (true) {
var node = _oldSourceUnitCursor.currentNode();
if (node === undefined) {
@ -391,15 +291,10 @@ module TypeScript.IncrementalParser {
return undefined;
}
if (!intersectsWithChangeRangeSpanInOriginalText(absolutePosition(), fullWidth(node))) {
// Didn't intersect with the change range.
var isIncrementallyUnusuable = TypeScript.isIncrementallyUnusable(node);
if (!isIncrementallyUnusuable) {
// Didn't contain anything that would make it unusable. Awesome. This is
// a node we can reuse.
return node;
}
if (!TypeScript.isIncrementallyUnusable(node)) {
// Didn't contain anything that would make it unusable. Awesome. This is
// a node we can reuse.
return node;
}
// We couldn't use currentNode. Try to move to its first child (in case that's a
@ -409,9 +304,9 @@ module TypeScript.IncrementalParser {
}
}
function canReuseTokenFromOldSourceUnit(position: number, token: ISyntaxToken): boolean {
function canReuseTokenFromOldSourceUnit(token: ISyntaxToken): boolean {
// A token is safe to return if:
// a) it does not intersect the changed text.
// a) it did not intersect the change range.
// b) it does not contain skipped text.
// c) it is not zero width.
// d) it is not a contextual parser token.
@ -427,33 +322,21 @@ module TypeScript.IncrementalParser {
// need to make sure that if that the parser asks for a *token* we don't return it.
// Converted identifiers can't ever be created by the scanner, and as such, should not
// be returned by this source.
if (token) {
if (!intersectsWithChangeRangeSpanInOriginalText(position, token.fullWidth())) {
// Didn't intersect with the change range.
if (!token.isIncrementallyUnusable() && !Scanner.isContextualToken(token)) {
// Didn't contain anything that would make it unusable. Awesome. This is
// a token we can reuse.
return true;
}
}
}
return false;
return token &&
!(<ISyntaxElementInternal><ISyntaxElement>token).intersectsChange &&
!token.isIncrementallyUnusable() &&
!Scanner.isContextualToken(token);
}
function tryGetTokenFromOldSourceUnit(): ISyntaxToken {
// Debug.assert(canReadFromOldSourceUnit());
// get the current token that the cursor is pointing at.
var token = _oldSourceUnitCursor.currentToken();
return canReuseTokenFromOldSourceUnit(absolutePosition(), token)
? token : undefined;
return canReuseTokenFromOldSourceUnit(token) ? token : undefined;
}
function peekToken(n: number): ISyntaxToken {
if (canReadFromOldSourceUnit()) {
if (trySynchronizeCursorToPosition()) {
var token = tryPeekTokenFromOldSourceUnit(n);
if (token) {
return token;
@ -465,8 +348,6 @@ module TypeScript.IncrementalParser {
}
function tryPeekTokenFromOldSourceUnit(n: number): ISyntaxToken {
// Debug.assert(canReadFromOldSourceUnit());
// clone the existing cursor so we can move it forward and then restore ourselves back
// to where we started from.
@ -481,11 +362,6 @@ module TypeScript.IncrementalParser {
}
function tryPeekTokenFromOldSourceUnitWorker(n: number): ISyntaxToken {
// In order to peek the 'nth' token we need all the tokens up to that point. That way
// we know we know position that the nth token is at. The position is necessary so
// that we can test if this token (or any that precede it cross the change range).
var currentPosition = absolutePosition();
// First, make sure the cursor is pointing at a token.
_oldSourceUnitCursor.moveToFirstToken();
@ -493,111 +369,31 @@ module TypeScript.IncrementalParser {
for (var i = 0; i < n; i++) {
var interimToken = _oldSourceUnitCursor.currentToken();
if (!canReuseTokenFromOldSourceUnit(currentPosition, interimToken)) {
if (!canReuseTokenFromOldSourceUnit(interimToken)) {
return undefined;
}
currentPosition += interimToken.fullWidth();
_oldSourceUnitCursor.moveToNextSibling();
}
var token = _oldSourceUnitCursor.currentToken();
return canReuseTokenFromOldSourceUnit(currentPosition, token)
? token : undefined;
return canReuseTokenFromOldSourceUnit(token) ? token : undefined;
}
function consumeNode(node: ISyntaxNode): void {
// A node could have only come from the old source unit cursor. Update it and our
// current state.
// Debug.assert(_changeDelta === 0);
// Debug.assert(currentNode() === node);
_oldSourceUnitCursor.moveToNextSibling();
// Update the underlying source with where it should now be currently pointin.
var _absolutePosition = absolutePosition() + fullWidth(node);
_scannerParserSource.resetToPosition(_absolutePosition);
// Debug.assert(previousToken !== undefined);
// Debug.assert(previousToken.width() > 0);
//if (!isPastChangeRange()) {
// // If we still have a change range, then this node must have ended before the
// // change range starts. Thus, we don't need to call 'skipPastChanges'.
// Debug.assert(absolutePosition() < _changeRange.span().start());
//}
}
function consumeToken(currentToken: ISyntaxToken): void {
// Debug.assert(currentToken.fullWidth() > 0 || currentToken.kind === SyntaxKind.EndOfFileToken);
// This token may have come from the old source unit, or from the new text. Handle
// both accordingly.
if (_oldSourceUnitCursor.currentToken() === currentToken) {
// The token came from the old source unit. So our tree and text must be in sync.
// Debug.assert(_changeDelta === 0);
// Move the cursor past this token.
_oldSourceUnitCursor.moveToNextSibling();
// Debug.assert(!_normalParserSource.isPinned());
// Update the underlying source with where it should now be currently pointing. We
// don't need to do this when the token came from the new text as the source will
// automatically be placed in the right position.
var _absolutePosition = absolutePosition() + currentToken.fullWidth();
_scannerParserSource.resetToPosition(_absolutePosition);
// Debug.assert(previousToken !== undefined);
// Debug.assert(previousToken.width() > 0);
//if (!isPastChangeRange()) {
// // If we still have a change range, then this token must have ended before the
// // change range starts. Thus, we don't need to call 'skipPastChanges'.
// Debug.assert(absolutePosition() < _changeRange.span().start());
//}
}
else {
// the token came from the new text. That means the normal source moved forward,
// while the syntax cursor stayed in the same place. Thus our delta moves even
// further back.
_changeDelta -= currentToken.fullWidth();
// Move our underlying source forward.
_scannerParserSource.consumeToken(currentToken);
// Because we read a token from the new text, we may have moved ourselves past the
// change range. If we did, then we may also have to update our change delta to
// compensate for the length change between the old and new text.
if (!isPastChangeRange()) {
// var changeEndInNewText = _changeRange.span().start() + _changeRange.newLength();
if (absolutePosition() >= _changeRangeNewSpan.end()) {
_changeDelta += _changeRange.newLength() - _changeRange.span().length();
// Once we're past the change range, we no longer need it. Null it out.
// From now on we can check if we're past the change range just by seeing
// if this is undefined.
_changeRange = undefined;
}
}
}
}
function isPastChangeRange(): boolean {
return _changeRange === undefined;
function consumeNodeOrToken(nodeOrToken: ISyntaxNodeOrToken): void {
_scannerParserSource.consumeNodeOrToken(nodeOrToken);
}
return {
text: text,
fileName: fileName,
languageVersion: languageVersion,
fileName: oldSyntaxTree.fileName(),
languageVersion: oldSyntaxTree.languageVersion(),
absolutePosition: absolutePosition,
currentNode: currentNode,
currentToken: currentToken,
currentContextualToken: currentContextualToken,
peekToken: peekToken,
consumeNode: consumeNode,
consumeToken: consumeToken,
consumeNodeOrToken: consumeNodeOrToken,
getRewindPoint: getRewindPoint,
rewind: rewind,
releaseRewindPoint: releaseRewindPoint,
@ -699,7 +495,6 @@ module TypeScript.IncrementalParser {
// Makes this cursor into a deep copy of the cursor passed in.
function deepCopyFrom(other: SyntaxCursor): void {
// Debug.assert(currentPieceIndex === -1);
for (var i = 0, n = other.pieces.length; i < n; i++) {
var piece = other.pieces[i];
@ -709,8 +504,6 @@ module TypeScript.IncrementalParser {
pushElement(piece.element, piece.indexInParent);
}
// Debug.assert(currentPieceIndex === other.currentPieceIndex);
}
function isFinished(): boolean {
@ -725,9 +518,6 @@ module TypeScript.IncrementalParser {
var result = pieces[currentPieceIndex].element;
// The current element must always be a node or a token.
// Debug.assert(result !== undefined);
// Debug.assert(result.isNode() || result.isToken());
return <ISyntaxNodeOrToken>result;
}
@ -751,9 +541,6 @@ module TypeScript.IncrementalParser {
return;
}
// The last element must be a token or a node.
// Debug.assert(isNode(nodeOrToken));
// Either the node has some existent child, then move to it. if it doesn't, then it's
// an empty node. Conceptually the first child of an empty node is really just the
// next sibling of the empty node.
@ -772,8 +559,6 @@ module TypeScript.IncrementalParser {
// This element must have been an empty node. Moving to its 'first child' is equivalent to just
// moving to the next sibling.
// Debug.assert(fullWidth(nodeOrToken) === 0);
moveToNextSibling();
}
@ -817,15 +602,11 @@ module TypeScript.IncrementalParser {
if (isList(element)) {
// We cannot ever get an empty list in our piece path. Empty lists are 'shared' and
// we make sure to filter that out before pushing any children.
// Debug.assert(childCount(element) > 0);
pushElement(childAt(element, 0), /*indexInParent:*/ 0);
}
}
function pushElement(element: ISyntaxElement, indexInParent: number): void {
// Debug.assert(element !== undefined);
// Debug.assert(indexInParent >= 0);
currentPieceIndex++;
// Reuse an existing piece if we have one. Otherwise, push a new piece to our list.
@ -847,7 +628,6 @@ module TypeScript.IncrementalParser {
continue;
}
// Debug.assert(isToken(element));
return;
}
}
@ -856,7 +636,6 @@ module TypeScript.IncrementalParser {
moveToFirstToken();
var element = currentNodeOrToken();
// Debug.assert(element === undefined || element.isToken());
return <ISyntaxToken>element;
}
@ -887,6 +666,94 @@ module TypeScript.IncrementalParser {
}
var tokenCollectorWalker = new TokenCollectorWalker();
function updateTokenPositionsAndMarkElements(element: ISyntaxElement, changeStart: number, changeRangeOldEnd: number, delta: number, fullStart: number): void {
// First, try to skip past any elements that we dont' need to move. We don't need to
// move any elements that don't start after the end of the change range.
if (fullStart > changeRangeOldEnd) {
// Note, we only move elements that are truly after the end of the change range.
// We consider elements that are touching the end of the change range to be unusable.
forceUpdateTokenPositionsForElement(element, delta);
}
else {
// Check if the element intersects the change range. If it does, then it is not
// reusable. Also, we'll need to recurse to see what constituent portions we may
// be able to use.
var fullEnd = fullStart + fullWidth(element);
if (fullEnd >= changeStart) {
(<ISyntaxElementInternal>element).intersectsChange = true;
if (isList(element)) {
var list = <ISyntaxNodeOrToken[]>element;
for (var i = 0, n = list.length; i < n; i++) {
var child: ISyntaxElement = list[i];
updateTokenPositionsAndMarkElements(child, changeStart, changeRangeOldEnd, delta, fullStart);
fullStart += fullWidth(child);
}
}
else if (isNode(element)) {
var node = <ISyntaxNode>element;
for (var i = 0, n = node.childCount; i < n; i++) {
var child = node.childAt(i);
if (child) {
updateTokenPositionsAndMarkElements(child, changeStart, changeRangeOldEnd, delta, fullStart);
fullStart += fullWidth(child);
}
}
}
}
// else {
// This element ended strictly before the edited range. We don't need to do anything
// with it.
// }
}
}
function forceUpdateTokenPositionsForElement(element: ISyntaxElement, delta: number) {
// No need to move anything if the delta is 0.
if (delta !== 0) {
if (isList(element)) {
var list = <ISyntaxNodeOrToken[]>element;
for (var i = 0, n = list.length; i < n; i++) {
forceUpdateTokenPositionForNodeOrToken(list[i], delta);
}
}
else {
forceUpdateTokenPositionForNodeOrToken(<ISyntaxNodeOrToken>element, delta);
}
}
}
function forceUpdateTokenPosition(token: ISyntaxToken, delta: number) {
token.setFullStart(token.fullStart() + delta);
}
function forceUpdateTokenPositionForNodeOrToken(nodeOrToken: ISyntaxNodeOrToken, delta: number) {
if (isToken(nodeOrToken)) {
forceUpdateTokenPosition(<ISyntaxToken>nodeOrToken, delta);
}
else {
var node = <ISyntaxNode>nodeOrToken;
var tokens = getTokens(node);
for (var i = 0, n = tokens.length; i < n; i++) {
forceUpdateTokenPosition(tokens[i], delta);
}
}
}
function getTokens(node: ISyntaxNode): ISyntaxToken[] {
var tokens = node.__cachedTokens;
if (!tokens) {
tokens = [];
tokenCollectorWalker.tokens = tokens;
visitNodeOrToken(tokenCollectorWalker, node);
node.__cachedTokens = tokens;
tokenCollectorWalker.tokens = undefined;
}
return tokens;
}
export function parse(oldSyntaxTree: SyntaxTree, textChangeRange: TextChangeRange, newText: ISimpleText): SyntaxTree {
if (textChangeRange.isUnchanged()) {

File diff suppressed because it is too large Load Diff

View File

@ -316,8 +316,8 @@ module TypeScript.PrettyPrinter {
this.appendToken(node.closeBraceToken);
}
private appendBlockOrSemicolon(body: BlockSyntax | ISyntaxToken) {
if (body.kind === SyntaxKind.Block) {
private appendBody(body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (body.kind === SyntaxKind.Block || body.kind === SyntaxKind.ExpressionBody) {
this.ensureSpace();
visitNodeOrToken(this, body);
}
@ -326,6 +326,12 @@ module TypeScript.PrettyPrinter {
}
}
public visitExpressionBody(node: ExpressionBody): void {
this.appendToken(node.equalsGreaterThanToken);
this.ensureSpace();
visitNodeOrToken(this, node.expression);
}
public visitFunctionDeclaration(node: FunctionDeclarationSyntax): void {
this.appendSpaceList(node.modifiers);
this.ensureSpace();
@ -333,7 +339,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
this.appendToken(node.identifier);
this.appendNode(node.callSignature);
this.appendBlockOrSemicolon(node.body);
this.appendBody(node.body);
}
public visitVariableStatement(node: VariableStatementSyntax): void {
@ -666,7 +672,7 @@ module TypeScript.PrettyPrinter {
public visitConstructorDeclaration(node: ConstructorDeclarationSyntax): void {
this.appendToken(node.constructorKeyword);
visitNodeOrToken(this, node.callSignature);
this.appendBlockOrSemicolon(node.body);
this.appendBody(node.body);
}
public visitIndexMemberDeclaration(node: IndexMemberDeclarationSyntax): void {
@ -681,7 +687,7 @@ module TypeScript.PrettyPrinter {
this.ensureSpace();
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.appendBlockOrSemicolon(node.body);
this.appendBody(node.body);
}
public visitGetAccessor(node: GetAccessorSyntax): void {
@ -692,7 +698,7 @@ module TypeScript.PrettyPrinter {
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.ensureSpace();
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitSetAccessor(node: SetAccessorSyntax): void {
@ -703,7 +709,7 @@ module TypeScript.PrettyPrinter {
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature)
this.ensureSpace();
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitMemberVariableDeclaration(node: MemberVariableDeclarationSyntax): void {
@ -936,7 +942,7 @@ module TypeScript.PrettyPrinter {
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
this.ensureSpace();
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitFunctionExpression(node: FunctionExpressionSyntax): void {
@ -949,7 +955,7 @@ module TypeScript.PrettyPrinter {
visitNodeOrToken(this, node.callSignature);
this.ensureSpace();
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitEmptyStatement(node: EmptyStatementSyntax): void {

View File

@ -281,7 +281,7 @@ module TypeScript.Scanner {
LargeScannerToken.prototype.childCount = 0;
export interface DiagnosticCallback {
(position: number, width: number, key: string, arguments: any[]): void;
(position: number, width: number, key: string, arguments?: any[]): void;
}
interface TokenInfo {
@ -1008,7 +1008,7 @@ module TypeScript.Scanner {
while (true) {
if (index === end) {
// Hit the end of the file.
reportDiagnostic(end, 0, DiagnosticCode._0_expected, ["`"]);
reportDiagnostic(end, 0, DiagnosticCode.Unterminated_template_literal);
break;
}
@ -1144,10 +1144,7 @@ module TypeScript.Scanner {
// term, and it sees one of these then it may restart us asking specifically if we could
// scan out a regex.
if (allowContextualToken) {
var result = tryScanRegularExpressionToken();
if (result !== SyntaxKind.None) {
return result;
}
return scanRegularExpressionToken();
}
if (str.charCodeAt(index) === CharacterCodes.equals) {
@ -1159,7 +1156,7 @@ module TypeScript.Scanner {
}
}
function tryScanRegularExpressionToken(): SyntaxKind {
function scanRegularExpressionToken(): SyntaxKind {
var startIndex = index;
var inEscape = false;
@ -1168,8 +1165,9 @@ module TypeScript.Scanner {
var ch = str.charCodeAt(index);
if (isNaN(ch) || isNewLineCharacter(ch)) {
index = startIndex;
return SyntaxKind.None;
// Hit the end of line, or end of the file. This is not a legal regex.
reportDiagnostic(index, 0, DiagnosticCode.Unterminated_regular_expression_literal);
break;
}
index++;
@ -1193,7 +1191,7 @@ module TypeScript.Scanner {
continue;
case CharacterCodes.closeBracket:
// If we ever hit a cloe bracket then we're now no longer in a character
// If we ever hit a close bracket then we're now no longer in a character
// class. If we weren't in a character class to begin with, then this has
// no effect.
inCharacterClass = false;
@ -1219,7 +1217,7 @@ module TypeScript.Scanner {
// TODO: The grammar says any identifier part is allowed here. Do we need to support
// \u identifiers here? The existing typescript parser does not.
while (isIdentifierPartCharacter[str.charCodeAt(index)]) {
while (index < end && isIdentifierPartCharacter[str.charCodeAt(index)]) {
index++;
}
@ -1322,7 +1320,7 @@ module TypeScript.Scanner {
break;
}
else if (isNaN(ch) || isNewLineCharacter(ch)) {
reportDiagnostic(Math.min(index, end), 1, DiagnosticCode.Missing_close_quote_character, undefined);
reportDiagnostic(index, 0, DiagnosticCode.Unterminated_string_literal);
break;
}
else {
@ -1432,16 +1430,6 @@ module TypeScript.Scanner {
return !hadError && SyntaxFacts.isIdentifierNameOrAnyKeyword(token) && width(token) === text.length();
}
// A parser source that gets its data from an underlying scanner.
export interface IScannerParserSource extends Parser.IParserSource {
// The position that the scanner is currently at.
absolutePosition(): number;
// Resets the source to this position. Any diagnostics produced after this point will be
// removed.
resetToPosition(absolutePosition: number): void;
}
interface IScannerRewindPoint extends Parser.IRewindPoint {
// Information used by normal parser source.
absolutePosition: number;
@ -1451,7 +1439,7 @@ module TypeScript.Scanner {
// Parser source used in batch scenarios. Directly calls into an underlying text scanner and
// supports none of the functionality to reuse nodes. Good for when you just want want to do
// a single parse of a file.
export function createParserSource(fileName: string, text: ISimpleText, languageVersion: ts.ScriptTarget): IScannerParserSource {
export function createParserSource(fileName: string, text: ISimpleText, languageVersion: ts.ScriptTarget): Parser.IParserSource {
// The absolute position we're at in the text we're reading from.
var _absolutePosition: number = 0;
@ -1491,11 +1479,6 @@ module TypeScript.Scanner {
return undefined;
}
function consumeNode(node: ISyntaxNode): void {
// Should never get called.
throw Errors.invalidOperation();
}
function absolutePosition() {
return _absolutePosition;
}
@ -1563,13 +1546,20 @@ module TypeScript.Scanner {
return slidingWindow.peekItemN(n);
}
function consumeToken(token: ISyntaxToken): void {
// Debug.assert(token.fullWidth() > 0 || token.kind === SyntaxKind.EndOfFileToken);
// Debug.assert(currentToken() === token);
_absolutePosition += token.fullWidth();
slidingWindow.moveToNextItem();
function consumeNodeOrToken(nodeOrToken: ISyntaxNodeOrToken): void {
if (nodeOrToken === slidingWindow.currentItemWithoutFetching()) {
// We're consuming the token that was just fetched from us by the parser. We just
// need to move ourselves forward and ditch this token from the sliding window.
_absolutePosition += (<ISyntaxToken>nodeOrToken).fullWidth();
slidingWindow.moveToNextItem();
}
else {
// We're either consuming a node, or we're consuming a token that wasn't from our
// sliding window. Both cases happen in incremental scenarios when the incremental
// parser uses a node or token from an older tree. In that case, we simply want to
// point ourselves at the end of the element that the parser just consumed.
resetToPosition(fullEnd(nodeOrToken));
}
}
function currentToken(): ISyntaxToken {
@ -1646,15 +1636,13 @@ module TypeScript.Scanner {
currentToken: currentToken,
currentContextualToken: currentContextualToken,
peekToken: peekToken,
consumeNode: consumeNode,
consumeToken: consumeToken,
consumeNodeOrToken: consumeNodeOrToken,
getRewindPoint: getRewindPoint,
rewind: rewind,
releaseRewindPoint: releaseRewindPoint,
tokenDiagnostics: tokenDiagnostics,
release: release,
absolutePosition: absolutePosition,
resetToPosition: resetToPosition,
};
}

View File

@ -163,6 +163,14 @@ module TypeScript {
return this.window[this.currentRelativeItemIndex];
}
public currentItemWithoutFetching(): any {
if (this.currentRelativeItemIndex >= this.windowCount) {
return undefined;
}
return this.window[this.currentRelativeItemIndex];
}
public peekItemN(n: number): any {
// Assert disabled because it is actually expensive enugh to affect perf.
// Debug.assert(n >= 0);

View File

@ -17,40 +17,29 @@ module TypeScript {
return undefined;
}
export function parsedInStrictModeContext(node: ISyntaxNode): boolean {
export function parserContextFlags(node: ISyntaxNode): ParserContextFlags {
var info = node.__data;
if (info === undefined) {
return false;
return 0;
}
return (info & SyntaxNodeConstants.ParsedInStrictModeContext) !== 0;
return info & ParserContextFlags.Mask;
}
export function parsedInStrictModeContext(node: ISyntaxNode): boolean {
return (parserContextFlags(node) & ParserContextFlags.StrictMode) !== 0;
}
export function parsedInDisallowInContext(node: ISyntaxNode): boolean {
var info = node.__data;
if (info === undefined) {
return false;
}
return (info & SyntaxNodeConstants.ParsedInDisallowInContext) !== 0;
return (parserContextFlags(node) & ParserContextFlags.DisallowIn) !== 0;
}
export function parsedInYieldContext(node: ISyntaxNode): boolean {
var info = node.__data;
if (info === undefined) {
return false;
}
return (info & SyntaxNodeConstants.ParsedInYieldContext) !== 0;
return (parserContextFlags(node) & ParserContextFlags.Yield) !== 0;
}
export function parsedInGeneratorParameterContext(node: ISyntaxNode): boolean {
var info = node.__data;
if (info === undefined) {
return false;
}
return (info & SyntaxNodeConstants.ParsedInGeneratorParameterContext) !== 0;
return (parserContextFlags(node) & ParserContextFlags.GeneratorParameter) !== 0;
}
export function previousToken(token: ISyntaxToken): ISyntaxToken {
@ -435,7 +424,7 @@ module TypeScript {
modifiers: ISyntaxToken[];
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface ISwitchClauseSyntax extends ISyntaxNode {

View File

@ -160,7 +160,15 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'asterixToken', isToken: true, isOptional: true },
<any>{ name: 'identifier', isToken: true },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
<any> {
name: 'ExpressionBody',
baseType: 'ISyntaxNode',
children: [
<any>{ name: 'equalsGreaterThanToken', isToken: true, },
<any>{ name: 'expression', type: 'IExpressionSyntax' }
]
},
<any>{
@ -392,7 +400,8 @@ var definitions:ITypeDefinition[] = [
baseType: 'ISyntaxNode',
interfaces: ['IStatementSyntax'],
children: [
<any>{ name: 'openBraceToken', isToken: true },
<any>{ name: 'equalsGreaterThanToken', isToken: true, isOptional: 'true' },
<any>{ name: 'openBraceToken', isToken: true, },
<any>{ name: 'statements', isList: true, elementType: 'IStatementSyntax' },
<any>{ name: 'closeBraceToken', isToken: true, excludeFromAST: true }
]
@ -435,7 +444,7 @@ var definitions:ITypeDefinition[] = [
children: [
<any>{ name: 'expression', type: 'ILeftHandSideExpressionSyntax' },
<any>{ name: 'openBracketToken', isToken: true, excludeFromAST: true },
<any>{ name: 'argumentExpression', type: 'IExpressionSyntax' },
<any>{ name: 'argumentExpression', type: 'IExpressionSyntax', isOptional: true },
<any>{ name: 'closeBracketToken', isToken: true, excludeFromAST: true }
]
},
@ -635,7 +644,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'modifiers', isList: true, elementType: 'ISyntaxToken' },
<any>{ name: 'constructorKeyword', isToken: true },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -648,7 +657,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'asterixToken', isToken: true, isOptional: true },
<any>{ name: 'propertyName', type: 'IPropertyNameSyntax' },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'body', type: 'BlockSyntax | ISyntaxToken', isOptional: true }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -661,7 +670,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'getKeyword', isToken: true, excludeFromAST: true },
<any>{ name: 'propertyName', type: 'IPropertyNameSyntax' },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'block', type: 'BlockSyntax' }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
<any>{
@ -673,7 +682,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'setKeyword', isToken: true, excludeFromAST: true },
<any>{ name: 'propertyName', type: 'IPropertyNameSyntax' },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'block', type: 'BlockSyntax' }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
],
isTypeScriptSpecific: true
},
@ -705,7 +714,7 @@ var definitions:ITypeDefinition[] = [
interfaces: ['IStatementSyntax'],
children: [
<any>{ name: 'throwKeyword', isToken: true, excludeFromAST: true },
<any>{ name: 'expression', type: 'IExpressionSyntax' },
<any>{ name: 'expression', type: 'IExpressionSyntax', isOptional: true },
<any>{ name: 'semicolonToken', isToken: true, isOptional: true, excludeFromAST: true }
]
},
@ -910,7 +919,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'asterixToken', isToken: true, isOptional: true },
<any>{ name: 'propertyName', type: 'IPropertyNameSyntax' },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'block', type: 'BlockSyntax' }
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }
]
},
<any>{
@ -922,7 +931,7 @@ var definitions:ITypeDefinition[] = [
<any>{ name: 'asterixToken', isToken: true, isOptional: true },
<any>{ name: 'identifier', isToken: true, isOptional: true },
<any>{ name: 'callSignature', type: 'CallSignatureSyntax' },
<any>{ name: 'block', type: 'BlockSyntax' }]
<any>{ name: 'body', type: 'BlockSyntax | ExpressionBody | ISyntaxToken', isOptional: true }]
},
<any>{
name: 'EmptyStatementSyntax',

View File

@ -95,9 +95,9 @@ module TypeScript {
asterixToken: ISyntaxToken;
identifier: ISyntaxToken;
callSignature: CallSignatureSyntax;
body: BlockSyntax | ISyntaxToken;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface FunctionDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken): FunctionDeclarationSyntax }
export interface FunctionDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): FunctionDeclarationSyntax }
export interface ModuleDeclarationSyntax extends ISyntaxNode, IModuleElementSyntax {
modifiers: ISyntaxToken[];
@ -154,9 +154,9 @@ module TypeScript {
asterixToken: ISyntaxToken;
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
body: BlockSyntax | ISyntaxToken;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface MemberFunctionDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken): MemberFunctionDeclarationSyntax }
export interface MemberFunctionDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): MemberFunctionDeclarationSyntax }
export interface MemberVariableDeclarationSyntax extends ISyntaxNode, IMemberDeclarationSyntax {
modifiers: ISyntaxToken[];
@ -169,9 +169,9 @@ module TypeScript {
modifiers: ISyntaxToken[];
constructorKeyword: ISyntaxToken;
callSignature: CallSignatureSyntax;
body: BlockSyntax | ISyntaxToken;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface ConstructorDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], constructorKeyword: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken): ConstructorDeclarationSyntax }
export interface ConstructorDeclarationConstructor { new (data: number, modifiers: ISyntaxToken[], constructorKeyword: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): ConstructorDeclarationSyntax }
export interface IndexMemberDeclarationSyntax extends ISyntaxNode, IClassElementSyntax {
modifiers: ISyntaxToken[];
@ -185,18 +185,18 @@ module TypeScript {
getKeyword: ISyntaxToken;
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface GetAccessorConstructor { new (data: number, modifiers: ISyntaxToken[], getKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax): GetAccessorSyntax }
export interface GetAccessorConstructor { new (data: number, modifiers: ISyntaxToken[], getKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): GetAccessorSyntax }
export interface SetAccessorSyntax extends ISyntaxNode, IAccessorSyntax {
modifiers: ISyntaxToken[];
setKeyword: ISyntaxToken;
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface SetAccessorConstructor { new (data: number, modifiers: ISyntaxToken[], setKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax): SetAccessorSyntax }
export interface SetAccessorConstructor { new (data: number, modifiers: ISyntaxToken[], setKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): SetAccessorSyntax }
export interface PropertySignatureSyntax extends ISyntaxNode, ITypeMemberSyntax {
propertyName: IPropertyNameSyntax;
@ -234,11 +234,12 @@ module TypeScript {
export interface MethodSignatureConstructor { new (data: number, propertyName: IPropertyNameSyntax, questionToken: ISyntaxToken, callSignature: CallSignatureSyntax): MethodSignatureSyntax }
export interface BlockSyntax extends ISyntaxNode, IStatementSyntax {
equalsGreaterThanToken: ISyntaxToken;
openBraceToken: ISyntaxToken;
statements: IStatementSyntax[];
closeBraceToken: ISyntaxToken;
}
export interface BlockConstructor { new (data: number, openBraceToken: ISyntaxToken, statements: IStatementSyntax[], closeBraceToken: ISyntaxToken): BlockSyntax }
export interface BlockConstructor { new (data: number, equalsGreaterThanToken: ISyntaxToken, openBraceToken: ISyntaxToken, statements: IStatementSyntax[], closeBraceToken: ISyntaxToken): BlockSyntax }
export interface IfStatementSyntax extends ISyntaxNode, IStatementSyntax {
ifKeyword: ISyntaxToken;
@ -503,9 +504,9 @@ module TypeScript {
asterixToken: ISyntaxToken;
identifier: ISyntaxToken;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface FunctionExpressionConstructor { new (data: number, functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, block: BlockSyntax): FunctionExpressionSyntax }
export interface FunctionExpressionConstructor { new (data: number, functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): FunctionExpressionSyntax }
export interface OmittedExpressionSyntax extends ISyntaxNode, IExpressionSyntax {
}
@ -650,9 +651,9 @@ module TypeScript {
asterixToken: ISyntaxToken;
propertyName: IPropertyNameSyntax;
callSignature: CallSignatureSyntax;
block: BlockSyntax;
body: BlockSyntax | ExpressionBody | ISyntaxToken;
}
export interface FunctionPropertyAssignmentConstructor { new (data: number, asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax): FunctionPropertyAssignmentSyntax }
export interface FunctionPropertyAssignmentConstructor { new (data: number, asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken): FunctionPropertyAssignmentSyntax }
export interface ParameterSyntax extends ISyntaxNode {
dotDotDotToken: ISyntaxToken;
@ -676,6 +677,12 @@ module TypeScript {
}
export interface TypeAnnotationConstructor { new (data: number, colonToken: ISyntaxToken, type: ITypeSyntax): TypeAnnotationSyntax }
export interface ExpressionBody extends ISyntaxNode {
equalsGreaterThanToken: ISyntaxToken;
expression: IExpressionSyntax;
}
export interface ExpressionBodyConstructor { new (data: number, equalsGreaterThanToken: ISyntaxToken, expression: IExpressionSyntax): ExpressionBody }
export interface ComputedPropertyNameSyntax extends ISyntaxNode, IPropertyNameSyntax {
openBracketToken: ISyntaxToken;
expression: IExpressionSyntax;

View File

@ -268,6 +268,7 @@ module TypeScript {
Parameter,
EnumElement,
TypeAnnotation,
ExpressionBody,
ComputedPropertyName,
ExternalModuleReference,
ModuleNameModuleReference,

View File

@ -38,7 +38,7 @@ module TypeScript {
module TypeScript.Syntax {
function addArrayPrototypeValue(name: string, val: any) {
if (Object.defineProperty && (<any>Array.prototype)[name] === undefined) {
Object.defineProperty(Array.prototype, name, { value: val, writable: false });
Object.defineProperty(Array.prototype, name, { value: val, writable: false, enumerable: false });
}
else {
(<any>Array.prototype)[name] = val;

View File

@ -238,7 +238,7 @@ module TypeScript {
}
}
export var FunctionDeclarationSyntax: FunctionDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken) {
export var FunctionDeclarationSyntax: FunctionDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.modifiers = modifiers,
this.functionKeyword = functionKeyword,
@ -406,7 +406,7 @@ module TypeScript {
}
}
export var MemberFunctionDeclarationSyntax: MemberFunctionDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken) {
export var MemberFunctionDeclarationSyntax: MemberFunctionDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.modifiers = modifiers,
this.asterixToken = asterixToken,
@ -450,7 +450,7 @@ module TypeScript {
}
}
export var ConstructorDeclarationSyntax: ConstructorDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], constructorKeyword: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ISyntaxToken) {
export var ConstructorDeclarationSyntax: ConstructorDeclarationConstructor = <any>function(data: number, modifiers: ISyntaxToken[], constructorKeyword: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.modifiers = modifiers,
this.constructorKeyword = constructorKeyword,
@ -491,18 +491,18 @@ module TypeScript {
}
}
export var GetAccessorSyntax: GetAccessorConstructor = <any>function(data: number, modifiers: ISyntaxToken[], getKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax) {
export var GetAccessorSyntax: GetAccessorConstructor = <any>function(data: number, modifiers: ISyntaxToken[], getKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.modifiers = modifiers,
this.getKeyword = getKeyword,
this.propertyName = propertyName,
this.callSignature = callSignature,
this.block = block,
this.body = body,
modifiers.parent = this,
getKeyword.parent = this,
propertyName.parent = this,
callSignature.parent = this,
block.parent = this;
body && (body.parent = this);
};
GetAccessorSyntax.prototype.kind = SyntaxKind.GetAccessor;
GetAccessorSyntax.prototype.childCount = 5;
@ -512,22 +512,22 @@ module TypeScript {
case 1: return this.getKeyword;
case 2: return this.propertyName;
case 3: return this.callSignature;
case 4: return this.block;
case 4: return this.body;
}
}
export var SetAccessorSyntax: SetAccessorConstructor = <any>function(data: number, modifiers: ISyntaxToken[], setKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax) {
export var SetAccessorSyntax: SetAccessorConstructor = <any>function(data: number, modifiers: ISyntaxToken[], setKeyword: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.modifiers = modifiers,
this.setKeyword = setKeyword,
this.propertyName = propertyName,
this.callSignature = callSignature,
this.block = block,
this.body = body,
modifiers.parent = this,
setKeyword.parent = this,
propertyName.parent = this,
callSignature.parent = this,
block.parent = this;
body && (body.parent = this);
};
SetAccessorSyntax.prototype.kind = SyntaxKind.SetAccessor;
SetAccessorSyntax.prototype.childCount = 5;
@ -537,7 +537,7 @@ module TypeScript {
case 1: return this.setKeyword;
case 2: return this.propertyName;
case 3: return this.callSignature;
case 4: return this.block;
case 4: return this.body;
}
}
@ -636,22 +636,25 @@ module TypeScript {
}
}
export var BlockSyntax: BlockConstructor = <any>function(data: number, openBraceToken: ISyntaxToken, statements: IStatementSyntax[], closeBraceToken: ISyntaxToken) {
export var BlockSyntax: BlockConstructor = <any>function(data: number, equalsGreaterThanToken: ISyntaxToken, openBraceToken: ISyntaxToken, statements: IStatementSyntax[], closeBraceToken: ISyntaxToken) {
if (data) { this.__data = data; }
this.equalsGreaterThanToken = equalsGreaterThanToken,
this.openBraceToken = openBraceToken,
this.statements = statements,
this.closeBraceToken = closeBraceToken,
equalsGreaterThanToken && (equalsGreaterThanToken.parent = this),
openBraceToken.parent = this,
statements.parent = this,
closeBraceToken.parent = this;
};
BlockSyntax.prototype.kind = SyntaxKind.Block;
BlockSyntax.prototype.childCount = 3;
BlockSyntax.prototype.childCount = 4;
BlockSyntax.prototype.childAt = function(index: number): ISyntaxElement {
switch (index) {
case 0: return this.openBraceToken;
case 1: return this.statements;
case 2: return this.closeBraceToken;
case 0: return this.equalsGreaterThanToken;
case 1: return this.openBraceToken;
case 2: return this.statements;
case 3: return this.closeBraceToken;
}
}
@ -893,7 +896,7 @@ module TypeScript {
this.expression = expression,
this.semicolonToken = semicolonToken,
throwKeyword.parent = this,
expression.parent = this,
expression && (expression.parent = this),
semicolonToken && (semicolonToken.parent = this);
};
ThrowStatementSyntax.prototype.kind = SyntaxKind.ThrowStatement;
@ -1347,7 +1350,7 @@ module TypeScript {
this.closeBracketToken = closeBracketToken,
expression.parent = this,
openBracketToken.parent = this,
argumentExpression.parent = this,
argumentExpression && (argumentExpression.parent = this),
closeBracketToken.parent = this;
};
ElementAccessExpressionSyntax.prototype.kind = SyntaxKind.ElementAccessExpression;
@ -1361,18 +1364,18 @@ module TypeScript {
}
}
export var FunctionExpressionSyntax: FunctionExpressionConstructor = <any>function(data: number, functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, block: BlockSyntax) {
export var FunctionExpressionSyntax: FunctionExpressionConstructor = <any>function(data: number, functionKeyword: ISyntaxToken, asterixToken: ISyntaxToken, identifier: ISyntaxToken, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.functionKeyword = functionKeyword,
this.asterixToken = asterixToken,
this.identifier = identifier,
this.callSignature = callSignature,
this.block = block,
this.body = body,
functionKeyword.parent = this,
asterixToken && (asterixToken.parent = this),
identifier && (identifier.parent = this),
callSignature.parent = this,
block.parent = this;
body && (body.parent = this);
};
FunctionExpressionSyntax.prototype.kind = SyntaxKind.FunctionExpression;
FunctionExpressionSyntax.prototype.childCount = 5;
@ -1382,7 +1385,7 @@ module TypeScript {
case 1: return this.asterixToken;
case 2: return this.identifier;
case 3: return this.callSignature;
case 4: return this.block;
case 4: return this.body;
}
}
@ -1760,16 +1763,16 @@ module TypeScript {
}
}
export var FunctionPropertyAssignmentSyntax: FunctionPropertyAssignmentConstructor = <any>function(data: number, asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, block: BlockSyntax) {
export var FunctionPropertyAssignmentSyntax: FunctionPropertyAssignmentConstructor = <any>function(data: number, asterixToken: ISyntaxToken, propertyName: IPropertyNameSyntax, callSignature: CallSignatureSyntax, body: BlockSyntax | ExpressionBody | ISyntaxToken) {
if (data) { this.__data = data; }
this.asterixToken = asterixToken,
this.propertyName = propertyName,
this.callSignature = callSignature,
this.block = block,
this.body = body,
asterixToken && (asterixToken.parent = this),
propertyName.parent = this,
callSignature.parent = this,
block.parent = this;
body && (body.parent = this);
};
FunctionPropertyAssignmentSyntax.prototype.kind = SyntaxKind.FunctionPropertyAssignment;
FunctionPropertyAssignmentSyntax.prototype.childCount = 4;
@ -1778,7 +1781,7 @@ module TypeScript {
case 0: return this.asterixToken;
case 1: return this.propertyName;
case 2: return this.callSignature;
case 3: return this.block;
case 3: return this.body;
}
}
@ -1842,6 +1845,22 @@ module TypeScript {
}
}
export var ExpressionBody: ExpressionBodyConstructor = <any>function(data: number, equalsGreaterThanToken: ISyntaxToken, expression: IExpressionSyntax) {
if (data) { this.__data = data; }
this.equalsGreaterThanToken = equalsGreaterThanToken,
this.expression = expression,
equalsGreaterThanToken.parent = this,
expression.parent = this;
};
ExpressionBody.prototype.kind = SyntaxKind.ExpressionBody;
ExpressionBody.prototype.childCount = 2;
ExpressionBody.prototype.childAt = function(index: number): ISyntaxElement {
switch (index) {
case 0: return this.equalsGreaterThanToken;
case 1: return this.expression;
}
}
export var ComputedPropertyNameSyntax: ComputedPropertyNameConstructor = <any>function(data: number, openBracketToken: ISyntaxToken, expression: IExpressionSyntax, closeBracketToken: ISyntaxToken) {
if (data) { this.__data = data; }
this.openBracketToken = openBracketToken,

View File

@ -290,8 +290,8 @@ module TypeScript.Syntax {
return new RealizedToken(token.fullStart(), token.kind, token.isKeywordConvertedToIdentifier(), leadingTrivia, token.text());
}
export function emptyToken(kind: SyntaxKind): ISyntaxToken {
return new EmptyToken(kind);
export function emptyToken(kind: SyntaxKind, fullStart: number): ISyntaxToken {
return new EmptyToken(kind, fullStart);
}
class EmptyToken implements ISyntaxToken {
@ -300,17 +300,17 @@ module TypeScript.Syntax {
public parent: ISyntaxElement;
public childCount: number;
constructor(public kind: SyntaxKind) {
constructor(public kind: SyntaxKind, private _fullStart: number) {
}
public setFullStart(fullStart: number): void {
// An empty token is always at the -1 position.
this._fullStart = fullStart;
}
public childAt(index: number): ISyntaxElement { throw Errors.invalidOperation() }
public clone(): ISyntaxToken {
return new EmptyToken(this.kind);
return new EmptyToken(this.kind, this._fullStart);
}
// Empty tokens are never incrementally reusable.
@ -321,75 +321,7 @@ module TypeScript.Syntax {
}
public fullWidth() { return 0; }
private position(): number {
// It's hard for us to tell the position of an empty token at the eact time we create
// it. For example, we may have:
//
// a / finally
//
// There will be a missing token detected after the forward slash, so it would be
// tempting to set its position as the full-end of hte slash token. However,
// immediately after that, the 'finally' token will be skipped and will be attached
// as skipped text to the forward slash. This means the 'full-end' of the forward
// slash will change, and thus the empty token will now appear to be embedded inside
// another token. This violates are rule that all tokens must only touch at the end,
// and makes enforcing invariants much harder.
//
// To address this we create the empty token with no known position, and then we
// determine what it's position should be based on where it lies in the tree.
// Specifically, we find the previous non-zero-width syntax element, and we consider
// the full-start of this token to be at the full-end of that element.
var previousElement = this.previousNonZeroWidthElement();
return !previousElement ? 0 : fullStart(previousElement) + fullWidth(previousElement);
}
private previousNonZeroWidthElement(): ISyntaxElement {
var current: ISyntaxElement = this;
while (true) {
var parent = current.parent;
if (parent === undefined) {
Debug.assert(current.kind === SyntaxKind.SourceUnit, "We had a node without a parent that was not the root node!");
// We walked all the way to the top, and never found a previous element. This
// can happen with code like:
//
// / b;
//
// We will have an empty identifier token as the first token in the tree. In
// this case, return undefined so that the position of the empty token will be
// considered to be 0.
return undefined;
}
// Ok. We have a parent. First, find out which slot we're at in the parent.
for (var i = 0, n = childCount(parent); i < n; i++) {
if (childAt(parent, i) === current) {
break;
}
}
Debug.assert(i !== n, "Could not find current element in parent's child list!");
// Walk backward from this element, looking for a non-zero-width sibling.
for (var j = i - 1; j >= 0; j--) {
var sibling = childAt(parent, j);
if (sibling && fullWidth(sibling) > 0) {
return sibling;
}
}
// We couldn't find a non-zero-width sibling. We were either the first element, or
// all preceding elements are empty. So, move up to our parent so we we can find
// its preceding sibling.
current = current.parent;
}
}
public fullStart(): number {
return this.position();
}
public fullStart(): number { return this._fullStart; }
public text() { return ""; }
public fullText(): string { return ""; }

View File

@ -138,8 +138,12 @@ module TypeScript {
}
private pushDiagnostic(element: ISyntaxElement, diagnosticKey: string, args?: any[]): void {
this.pushDiagnosticAt(start(element, this.text), width(element), diagnosticKey, args);
}
private pushDiagnosticAt(start: number, length: number, diagnosticKey: string, args?: any[]): void {
this.diagnostics.push(new Diagnostic(
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), start(element, this.text), width(element), diagnosticKey, args));
this.syntaxTree.fileName(), this.syntaxTree.lineMap(), start, length, diagnosticKey, args));
}
public visitCatchClause(node: CatchClauseSyntax): void {
@ -631,13 +635,27 @@ module TypeScript {
this.checkClassElementModifiers(node.modifiers) ||
this.checkForDisallowedAccessorTypeParameters(node.callSignature) ||
this.checkGetAccessorParameter(node) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForSemicolonInsteadOfBlock(node, node.body)) {
return;
}
super.visitGetAccessor(node);
}
private checkForSemicolonInsteadOfBlock(parent: ISyntaxNode, node: BlockSyntax | ExpressionBody | ISyntaxToken): boolean {
if (node === undefined) {
this.pushDiagnosticAt(fullEnd(parent), 0, DiagnosticCode._0_expected, ["{"]);
return true;
}
else if (node.kind === SyntaxKind.SemicolonToken) {
this.pushDiagnostic(node, DiagnosticCode._0_expected, ["{"]);
return true;
}
return false;
}
private checkForDisallowedSetAccessorTypeAnnotation(accessor: SetAccessorSyntax): boolean {
if (accessor.callSignature.typeAnnotation) {
this.pushDiagnostic(accessor.callSignature.typeAnnotation, DiagnosticCode.Type_annotation_cannot_appear_on_a_set_accessor);
@ -708,13 +726,41 @@ module TypeScript {
this.checkForDisallowedAccessorTypeParameters(node.callSignature) ||
this.checkForDisallowedSetAccessorTypeAnnotation(node) ||
this.checkSetAccessorParameter(node) ||
this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForSemicolonInsteadOfBlock(node, node.body)) {
return;
}
super.visitSetAccessor(node);
}
public visitElementAccessExpression(node: ElementAccessExpressionSyntax): void {
if (this.checkForMissingArgumentExpression(node)) {
return;
}
super.visitElementAccessExpression(node);
}
public checkForMissingArgumentExpression(node: ElementAccessExpressionSyntax): boolean {
if (node.argumentExpression === undefined) {
if (node.parent.kind === SyntaxKind.ObjectCreationExpression && (<ObjectCreationExpressionSyntax>node.parent).expression === node) {
// Provide a specialized message for the very common case where someone writes:
// new Foo[]
var start = TypeScript.start(node.openBracketToken);
var end = TypeScript.fullEnd(node.closeBracketToken);
this.pushDiagnosticAt(start, end - start, DiagnosticCode.new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead);
}
else {
this.pushDiagnostic(node.closeBracketToken, DiagnosticCode.Expression_expected);
}
return true;
}
return false;
}
public visitEnumDeclaration(node: EnumDeclarationSyntax): void {
if (this.checkForDisallowedDeclareModifier(node.modifiers) ||
this.checkForRequiredDeclareModifier(node, node.identifier, node.modifiers) ||
@ -887,7 +933,8 @@ module TypeScript {
}
public visitBlock(node: BlockSyntax): void {
if (this.checkForBlockInAmbientContext(node)) {
if (this.checkForBlockInAmbientContext(node) ||
this.checkForMalformedBlock(node)) {
return;
}
@ -897,6 +944,15 @@ module TypeScript {
this.inBlock = savedInBlock;
}
public checkForMalformedBlock(node: BlockSyntax): boolean {
if (node.equalsGreaterThanToken || node.openBraceToken === undefined) {
this.pushDiagnostic(firstToken(node), DiagnosticCode._0_expected, ["{"]);
return true;
}
return false;
}
private checkForBlockInAmbientContext(node: BlockSyntax): boolean {
if (this.inAmbientDeclaration || this.syntaxTree.isDeclaration()) {
// Provide a specialized message for a block as a statement versus the block as a
@ -923,6 +979,11 @@ module TypeScript {
return false;
}
public visitExpressionBody(node: ExpressionBody): void {
// These are always errors. So no need to ever recurse on them.
this.pushDiagnostic(node.equalsGreaterThanToken, DiagnosticCode._0_expected, ["{"]);
}
public visitBreakStatement(node: BreakStatementSyntax): void {
if (this.checkForStatementInAmbientContxt(node) ||
this.checkBreakStatementTarget(node)) {
@ -1264,13 +1325,23 @@ module TypeScript {
}
public visitThrowStatement(node: ThrowStatementSyntax): void {
if (this.checkForStatementInAmbientContxt(node)) {
if (this.checkForStatementInAmbientContxt(node) ||
this.checkForMissingThrowStatementExpression(node)) {
return;
}
super.visitThrowStatement(node);
}
public checkForMissingThrowStatementExpression(node: ThrowStatementSyntax): boolean {
if (node.expression === undefined) {
this.pushDiagnosticAt(fullEnd(node.throwKeyword), 0, DiagnosticCode.Expression_expected);
return true;
}
return false;
}
public visitTryStatement(node: TryStatementSyntax): void {
if (this.checkForStatementInAmbientContxt(node)) {
return;
@ -1333,7 +1404,8 @@ module TypeScript {
}
public visitFunctionExpression(node: FunctionExpressionSyntax): void {
if (this.checkForDisallowedEvalOrArguments(node, node.identifier)) {
if (this.checkForDisallowedEvalOrArguments(node, node.identifier) ||
this.checkForSemicolonInsteadOfBlock(node, node.body)) {
return;
}
@ -1341,7 +1413,8 @@ module TypeScript {
}
public visitFunctionPropertyAssignment(node: FunctionPropertyAssignmentSyntax): void {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName)) {
if (this.checkForDisallowedTemplatePropertyName(node.propertyName) ||
this.checkForSemicolonInsteadOfBlock(node, node.body)) {
return;
}

View File

@ -94,6 +94,7 @@ module TypeScript {
case SyntaxKind.Parameter: return visitor.visitParameter(<ParameterSyntax>element);
case SyntaxKind.EnumElement: return visitor.visitEnumElement(<EnumElementSyntax>element);
case SyntaxKind.TypeAnnotation: return visitor.visitTypeAnnotation(<TypeAnnotationSyntax>element);
case SyntaxKind.ExpressionBody: return visitor.visitExpressionBody(<ExpressionBody>element);
case SyntaxKind.ComputedPropertyName: return visitor.visitComputedPropertyName(<ComputedPropertyNameSyntax>element);
case SyntaxKind.ExternalModuleReference: return visitor.visitExternalModuleReference(<ExternalModuleReferenceSyntax>element);
case SyntaxKind.ModuleNameModuleReference: return visitor.visitModuleNameModuleReference(<ModuleNameModuleReferenceSyntax>element);
@ -193,6 +194,7 @@ module TypeScript {
visitParameter(node: ParameterSyntax): any;
visitEnumElement(node: EnumElementSyntax): any;
visitTypeAnnotation(node: TypeAnnotationSyntax): any;
visitExpressionBody(node: ExpressionBody): any;
visitComputedPropertyName(node: ComputedPropertyNameSyntax): any;
visitExternalModuleReference(node: ExternalModuleReferenceSyntax): any;
visitModuleNameModuleReference(node: ModuleNameModuleReferenceSyntax): any;

View File

@ -180,7 +180,7 @@ module TypeScript {
this.visitToken(node.getKeyword);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitSetAccessor(node: SetAccessorSyntax): void {
@ -188,7 +188,7 @@ module TypeScript {
this.visitToken(node.setKeyword);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitPropertySignature(node: PropertySignatureSyntax): void {
@ -222,6 +222,7 @@ module TypeScript {
}
public visitBlock(node: BlockSyntax): void {
this.visitOptionalToken(node.equalsGreaterThanToken);
this.visitToken(node.openBraceToken);
this.visitList(node.statements);
this.visitToken(node.closeBraceToken);
@ -456,7 +457,7 @@ module TypeScript {
this.visitOptionalToken(node.asterixToken);
this.visitOptionalToken(node.identifier);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitOmittedExpression(node: OmittedExpressionSyntax): void {
@ -581,7 +582,7 @@ module TypeScript {
this.visitOptionalToken(node.asterixToken);
visitNodeOrToken(this, node.propertyName);
visitNodeOrToken(this, node.callSignature);
visitNodeOrToken(this, node.block);
visitNodeOrToken(this, node.body);
}
public visitParameter(node: ParameterSyntax): void {
@ -603,6 +604,11 @@ module TypeScript {
visitNodeOrToken(this, node.type);
}
public visitExpressionBody(node: ExpressionBody): void {
this.visitToken(node.equalsGreaterThanToken);
visitNodeOrToken(this, node.expression);
}
public visitComputedPropertyName(node: ComputedPropertyNameSyntax): void {
this.visitToken(node.openBracketToken);
visitNodeOrToken(this, node.expression);

296
src/services/text.ts Normal file
View File

@ -0,0 +1,296 @@
module ts {
export class TextSpan {
private _start: number;
private _length: number;
/**
* Creates a TextSpan instance beginning with the position Start and having the Length
* specified with length.
*/
constructor(start: number, length: number) {
Debug.assert(start >= 0, "start");
Debug.assert(length >= 0, "length");
this._start = start;
this._length = length;
}
public toJSON(key: any): any {
return { start: this._start, length: this._length };
}
public start(): number {
return this._start;
}
public length(): number {
return this._length;
}
public end(): number {
return this._start + this._length;
}
public isEmpty(): boolean {
return this._length === 0;
}
/**
* Determines whether the position lies within the span. Returns true if the position is greater than or equal to Start and strictly less
* than End, otherwise false.
* @param position The position to check.
*/
public containsPosition(position: number): boolean {
return position >= this._start && position < this.end();
}
/**
* Determines whether span falls completely within this span. Returns true if the specified span falls completely within this span, otherwise false.
* @param span The span to check.
*/
public containsTextSpan(span: TextSpan): boolean {
return span._start >= this._start && span.end() <= this.end();
}
/**
* Determines whether the given span overlaps this span. Two spans are considered to overlap
* if they have positions in common and neither is empty. Empty spans do not overlap with any
* other span. Returns true if the spans overlap, false otherwise.
* @param span The span to check.
*/
public overlapsWith(span: TextSpan): boolean {
var overlapStart = Math.max(this._start, span._start);
var overlapEnd = Math.min(this.end(), span.end());
return overlapStart < overlapEnd;
}
/**
* Returns the overlap with the given span, or undefined if there is no overlap.
* @param span The span to check.
*/
public overlap(span: TextSpan): TextSpan {
var overlapStart = Math.max(this._start, span._start);
var overlapEnd = Math.min(this.end(), span.end());
if (overlapStart < overlapEnd) {
return TextSpan.fromBounds(overlapStart, overlapEnd);
}
return undefined;
}
/**
* Determines whether span intersects this span. Two spans are considered to
* intersect if they have positions in common or the end of one span
* coincides with the start of the other span. Returns true if the spans intersect, false otherwise.
* @param The span to check.
*/
public intersectsWithTextSpan(span: TextSpan): boolean {
return span._start <= this.end() && span.end() >= this._start;
}
public intersectsWith(start: number, length: number): boolean {
var end = start + length;
return start <= this.end() && end >= this._start;
}
/**
* Determines whether the given position intersects this span.
* A position is considered to intersect if it is between the start and
* end positions (inclusive) of this span. Returns true if the position intersects, false otherwise.
* @param position The position to check.
*/
public intersectsWithPosition(position: number): boolean {
return position <= this.end() && position >= this._start;
}
/**
* Returns the intersection with the given span, or undefined if there is no intersection.
* @param span The span to check.
*/
public intersection(span: TextSpan): TextSpan {
var intersectStart = Math.max(this._start, span._start);
var intersectEnd = Math.min(this.end(), span.end());
if (intersectStart <= intersectEnd) {
return TextSpan.fromBounds(intersectStart, intersectEnd);
}
return undefined;
}
/**
* Creates a new TextSpan from the given start and end positions
* as opposed to a position and length.
*/
public static fromBounds(start: number, end: number): TextSpan {
Debug.assert(start >= 0);
Debug.assert(end - start >= 0);
return new TextSpan(start, end - start);
}
}
export class TextChangeRange {
public static unchanged = new TextChangeRange(new TextSpan(0, 0), 0);
private _span: TextSpan;
private _newLength: number;
/**
* Initializes a new instance of TextChangeRange.
*/
constructor(span: TextSpan, newLength: number) {
Debug.assert(newLength >= 0, "newLength");
this._span = span;
this._newLength = newLength;
}
/**
* The span of text before the edit which is being changed
*/
public span(): TextSpan {
return this._span;
}
/**
* Width of the span after the edit. A 0 here would represent a delete
*/
public newLength(): number {
return this._newLength;
}
public newSpan(): TextSpan {
return new TextSpan(this.span().start(), this.newLength());
}
public isUnchanged(): boolean {
return this.span().isEmpty() && this.newLength() === 0;
}
/**
* Called to merge all the changes that occurred across several versions of a script snapshot
* into a single change. i.e. if a user keeps making successive edits to a script we will
* have a text change from V1 to V2, V2 to V3, ..., Vn.
*
* This function will then merge those changes into a single change range valid between V1 and
* Vn.
*/
public static collapseChangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange {
if (changes.length === 0) {
return TextChangeRange.unchanged;
}
if (changes.length === 1) {
return changes[0];
}
// We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
// as it makes things much easier to reason about.
var change0 = changes[0];
var oldStartN = change0.span().start();
var oldEndN = change0.span().end();
var newEndN = oldStartN + change0.newLength();
for (var i = 1; i < changes.length; i++) {
var nextChange = changes[i];
// Consider the following case:
// i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting
// at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }.
// i.e. the span starting at 30 with length 30 is increased to length 40.
//
// 0 10 20 30 40 50 60 70 80 90 100
// -------------------------------------------------------------------------------------------------------
// | /
// | /----
// T1 | /----
// | /----
// | /----
// -------------------------------------------------------------------------------------------------------
// | \
// | \
// T2 | \
// | \
// | \
// -------------------------------------------------------------------------------------------------------
//
// Merging these turns out to not be too difficult. First, determining the new start of the change is trivial
// it's just the min of the old and new starts. i.e.:
//
// 0 10 20 30 40 50 60 70 80 90 100
// ------------------------------------------------------------*------------------------------------------
// | /
// | /----
// T1 | /----
// | /----
// | /----
// ----------------------------------------$-------------------$------------------------------------------
// . | \
// . | \
// T2 . | \
// . | \
// . | \
// ----------------------------------------------------------------------*--------------------------------
//
// (Note the dots represent the newly inferrred start.
// Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the
// absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see
// which if the two $'s precedes the other, and we move that one forward until they line up. in this case that
// means:
//
// 0 10 20 30 40 50 60 70 80 90 100
// --------------------------------------------------------------------------------*----------------------
// | /
// | /----
// T1 | /----
// | /----
// | /----
// ------------------------------------------------------------$------------------------------------------
// . | \
// . | \
// T2 . | \
// . | \
// . | \
// ----------------------------------------------------------------------*--------------------------------
//
// In other words (in this case), we're recognizing that the second edit happened after where the first edit
// ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started
// that's the same as if we started at char 80 instead of 60.
//
// As it so happens, the same logic applies if the second edit precedes the first edit. In that case rahter
// than pusing the first edit forward to match the second, we'll push the second edit forward to match the
// first.
//
// In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange
// semantics: { { start: 10, length: 70 }, newLength: 60 }
//
// The math then works out as follows.
// If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the
// final result like so:
//
// {
// oldStart3: Min(oldStart1, oldStart2),
// oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
// newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
// }
var oldStart1 = oldStartN;
var oldEnd1 = oldEndN;
var newEnd1 = newEndN;
var oldStart2 = nextChange.span().start();
var oldEnd2 = nextChange.span().end();
var newEnd2 = oldStart2 + nextChange.newLength();
oldStartN = Math.min(oldStart1, oldStart2);
oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
}
return new TextChangeRange(TextSpan.fromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN);
}
}
}

View File

@ -66,22 +66,22 @@ module ts {
}
export function findListItemInfo(node: Node): ListItemInfo {
var syntaxList = findContainingList(node);
var list = 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) {
if (!list) {
return undefined;
}
var children = syntaxList.getChildren();
var index = indexOf(children, node);
var children = list.getChildren();
var listItemIndex = indexOf(children, node);
return {
listItemIndex: index,
list: syntaxList
listItemIndex,
list
};
}
@ -320,4 +320,9 @@ module ts {
export function isPunctuation(kind: SyntaxKind): boolean {
return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation;
}
export function isInsideTemplateLiteral(node: LiteralExpression, position: number) {
return (node.getStart() < position && position < node.getEnd())
|| (isUnterminatedTemplateEnd(node) && position === node.getEnd());
}
}

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName10_es6.ts(2,8): error TS1005: ';' expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName10_es6.ts (1 errors) ====
class C {
[e] = 1
~
!!! error TS1005: ';' expected.
}

View File

@ -0,0 +1,15 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName11_es6.ts(2,7): error TS1005: ';' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName11_es6.ts(2,8): error TS1109: Expression expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName11_es6.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName11_es6.ts (3 errors) ====
class C {
[e]();
~
!!! error TS1005: ';' expected.
~
!!! error TS1109: Expression expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,15 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName12_es6.ts(2,7): error TS1005: ';' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName12_es6.ts(2,10): error TS1005: '=>' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName12_es6.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName12_es6.ts (3 errors) ====
class C {
[e]() { }
~
!!! error TS1005: ';' expected.
~
!!! error TS1005: '=>' expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName13_es6.ts(1,11): error TS1022: An index signature parameter must have a type annotation.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName13_es6.ts (1 errors) ====
var v: { [e]: number };
~
!!! error TS1022: An index signature parameter must have a type annotation.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName14_es6.ts(1,13): error TS1005: ';' expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName14_es6.ts (1 errors) ====
var v: { [e](): number };
~
!!! error TS1005: ';' expected.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName15_es6.ts(1,32): error TS1022: An index signature parameter must have a type annotation.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName15_es6.ts (1 errors) ====
var v: { [e: number]: string; [e]: number };
~
!!! error TS1022: An index signature parameter must have a type annotation.

View File

@ -0,0 +1,18 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName16_es6.ts(2,3): error TS1132: Enum member expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName16_es6.ts(3,1): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName16_es6.ts(2,3): error TS2364: Invalid left-hand side of assignment expression.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName16_es6.ts(2,4): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName16_es6.ts (4 errors) ====
enum E {
[e] = 1
~
!!! error TS1132: Enum member expected.
~~~
!!! error TS2364: Invalid left-hand side of assignment expression.
~
!!! error TS2304: Cannot find name 'e'.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName17_es6.ts(1,15): error TS1003: Identifier expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName17_es6.ts(1,22): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName17_es6.ts(1,26): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName17_es6.ts(1,16): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName17_es6.ts (4 errors) ====
var v = { set [e](v) { } }
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName18_es6.ts(1,13): error TS1005: ';' expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName18_es6.ts (1 errors) ====
var v: { [e]?(): number };
~
!!! error TS1005: ';' expected.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName19_es6.ts(1,13): error TS1005: ';' expected.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName19_es6.ts (1 errors) ====
var v: { [e]? };
~
!!! error TS1005: ';' expected.

View File

@ -0,0 +1,13 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName1_es6.ts(1,11): error TS1136: Property assignment expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName1_es6.ts(1,15): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName1_es6.ts(1,12): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName1_es6.ts (3 errors) ====
var v = { [e] };
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,19 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts(1,11): error TS1136: Property assignment expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts(1,14): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts(1,16): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts(1,18): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts(1,12): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName2_es6.ts (5 errors) ====
var v = { [e]: 1 };
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1134: Variable declaration expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName3_es6.ts(1,11): error TS1136: Property assignment expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName3_es6.ts(1,17): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName3_es6.ts(1,21): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName3_es6.ts(1,12): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName3_es6.ts (4 errors) ====
var v = { [e]() { } };
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName4_es6.ts(1,15): error TS1003: Identifier expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName4_es6.ts(1,21): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName4_es6.ts(1,25): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName4_es6.ts(1,16): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName4_es6.ts (4 errors) ====
var v = { get [e]() { } };
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,19 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts(1,18): error TS1005: ':' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts(1,28): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts(1,32): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts(1,18): error TS2304: Cannot find name 'get'.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts(1,23): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName5_es6.ts (5 errors) ====
var v = { public get [e]() { } };
~~~
!!! error TS1005: ':' expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~
!!! error TS2304: Cannot find name 'get'.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,28 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,11): error TS1136: Property assignment expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,14): error TS1005: ',' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,16): error TS1134: Variable declaration expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,26): error TS1005: ';' expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,30): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,12): error TS2304: Cannot find name 'e'.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,20): error TS2304: Cannot find name 'e'.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts(1,24): error TS2304: Cannot find name 'e'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName6_es6.ts (8 errors) ====
var v = { [e]: 1, [e + e]: 2 };
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1134: Variable declaration expected.
~
!!! error TS1005: ';' expected.
~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS2304: Cannot find name 'e'.
~
!!! error TS2304: Cannot find name 'e'.
~
!!! error TS2304: Cannot find name 'e'.

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName7_es6.ts(2,5): error TS1022: An index signature parameter must have a type annotation.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName7_es6.ts (1 errors) ====
class C {
[e]
~
!!! error TS1022: An index signature parameter must have a type annotation.
}

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName8_es6.ts(2,12): error TS1022: An index signature parameter must have a type annotation.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName8_es6.ts (1 errors) ====
class C {
public [e]
~
!!! error TS1022: An index signature parameter must have a type annotation.
}

View File

@ -0,0 +1,12 @@
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName9_es6.ts(2,5): error TS1022: An index signature parameter must have a type annotation.
tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName9_es6.ts(2,9): error TS2304: Cannot find name 'Type'.
==== tests/cases/conformance/es6/computedPropertyNames/ComputedPropertyName9_es6.ts (2 errors) ====
class C {
[e]: Type
~
!!! error TS1022: An index signature parameter must have a type annotation.
~~~~
!!! error TS2304: Cannot find name 'Type'.
}

View File

@ -0,0 +1,8 @@
//// [FunctionDeclaration10_es6.ts]
function * foo(a = yield => yield) {
}
//// [FunctionDeclaration10_es6.js]
function foo(a) {
if (a === void 0) { a = function (yield) { return yield; }; }
}

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration10_es6.ts ===
function * foo(a = yield => yield) {
>foo : (a?: (yield: any) => any) => void
>a : (yield: any) => any
>yield => yield : (yield: any) => any
>yield : any
>yield : any
}

View File

@ -0,0 +1,7 @@
//// [FunctionDeclaration11_es6.ts]
function * yield() {
}
//// [FunctionDeclaration11_es6.js]
function yield() {
}

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts ===
function * yield() {
>yield : () => void
}

View File

@ -0,0 +1,13 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration12_es6.ts(1,20): error TS1005: '(' expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration12_es6.ts(1,25): error TS1005: '=' expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration12_es6.ts(1,28): error TS1005: '=>' expected.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration12_es6.ts (3 errors) ====
var v = function * yield() { }
~~~~~
!!! error TS1005: '(' expected.
~
!!! error TS1005: '=' expected.
~
!!! error TS1005: '=>' expected.

View File

@ -0,0 +1,11 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(3,11): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts (1 errors) ====
function * foo() {
// Legal to use 'yield' in a type context.
var v: yield;
~~~~~
!!! error TS2304: Cannot find name 'yield'.
}

View File

@ -0,0 +1,12 @@
//// [FunctionDeclaration13_es6.ts]
function * foo() {
// Legal to use 'yield' in a type context.
var v: yield;
}
//// [FunctionDeclaration13_es6.js]
function foo() {
// Legal to use 'yield' in a type context.
var v;
}

View File

@ -0,0 +1,7 @@
//// [FunctionDeclaration1_es6.ts]
function * foo() {
}
//// [FunctionDeclaration1_es6.js]
function foo() {
}

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts ===
function * foo() {
>foo : () => void
}

View File

@ -0,0 +1,7 @@
//// [FunctionDeclaration2_es6.ts]
function f(yield) {
}
//// [FunctionDeclaration2_es6.js]
function f(yield) {
}

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration2_es6.ts ===
function f(yield) {
>f : (yield: any) => void
>yield : any
}

View File

@ -0,0 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration3_es6.ts(1,20): error TS2372: Parameter 'yield' cannot be referenced in its initializer.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration3_es6.ts (1 errors) ====
function f(yield = yield) {
~~~~~
!!! error TS2372: Parameter 'yield' cannot be referenced in its initializer.
}

View File

@ -0,0 +1,8 @@
//// [FunctionDeclaration3_es6.ts]
function f(yield = yield) {
}
//// [FunctionDeclaration3_es6.js]
function f(yield) {
if (yield === void 0) { yield = yield; }
}

View File

@ -0,0 +1,7 @@
//// [FunctionDeclaration4_es6.ts]
function yield() {
}
//// [FunctionDeclaration4_es6.js]
function yield() {
}

View File

@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration4_es6.ts ===
function yield() {
>yield : () => void
}

View File

@ -0,0 +1,17 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration5_es6.ts(1,14): error TS1138: Parameter declaration expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration5_es6.ts(1,19): error TS1005: ';' expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration5_es6.ts(1,10): error TS2391: Function implementation is missing or not immediately following the declaration.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration5_es6.ts(1,14): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration5_es6.ts (4 errors) ====
function*foo(yield) {
~~~~~
!!! error TS1138: Parameter declaration expected.
~
!!! error TS1005: ';' expected.
~~~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
~~~~~
!!! error TS2304: Cannot find name 'yield'.
}

View File

@ -0,0 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,18): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts (1 errors) ====
function*foo(a = yield) {
~~~~~
!!! error TS2304: Cannot find name 'yield'.
}

View File

@ -0,0 +1,8 @@
//// [FunctionDeclaration6_es6.ts]
function*foo(a = yield) {
}
//// [FunctionDeclaration6_es6.js]
function foo(a) {
if (a === void 0) { a = yield; }
}

View File

@ -0,0 +1,11 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,20): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts (1 errors) ====
function*bar() {
// 'yield' here is an identifier, and not a yield expression.
function*foo(a = yield) {
~~~~~
!!! error TS2304: Cannot find name 'yield'.
}
}

View File

@ -0,0 +1,14 @@
//// [FunctionDeclaration7_es6.ts]
function*bar() {
// 'yield' here is an identifier, and not a yield expression.
function*foo(a = yield) {
}
}
//// [FunctionDeclaration7_es6.js]
function bar() {
// 'yield' here is an identifier, and not a yield expression.
function foo(a) {
if (a === void 0) { a = yield; }
}
}

View File

@ -0,0 +1,16 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,11): error TS1136: Property assignment expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,18): error TS1005: ',' expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,24): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts(1,12): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration8_es6.ts (4 errors) ====
var v = { [yield]: foo }
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
~
!!! error TS1128: Declaration or statement expected.
~~~~~
!!! error TS2304: Cannot find name 'yield'.

View File

@ -0,0 +1,15 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(2,13): error TS1136: Property assignment expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(2,20): error TS1005: ',' expected.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts (3 errors) ====
function * foo() {
var v = { [yield]: foo }
~
!!! error TS1136: Property assignment expected.
~
!!! error TS1005: ',' expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,6 @@
//// [FunctionExpression1_es6.ts]
var v = function * () { }
//// [FunctionExpression1_es6.js]
var v = function () {
};

View File

@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts ===
var v = function * () { }
>v : () => void
>function * () { } : () => void

Some files were not shown because too many files have changed in this diff Show More