mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-28 08:57:35 -06:00
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:
commit
d3e70ecfbf
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
4
bin/lib.core.d.ts
vendored
@ -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
4
bin/lib.d.ts
vendored
@ -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
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
@ -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 {
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -153,9 +153,9 @@ module ts {
|
||||
|
||||
parseStrings(commandLine);
|
||||
return {
|
||||
options: options,
|
||||
filenames: filenames,
|
||||
errors: errors
|
||||
options,
|
||||
filenames,
|
||||
errors
|
||||
};
|
||||
|
||||
function parseStrings(args: string[]) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -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
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
///<reference path='..\text.ts' />
|
||||
///<reference path='..\services.ts' />
|
||||
///<reference path='formattingContext.ts' />
|
||||
///<reference path='formattingRequestKind.ts' />
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.",
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -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
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
@ -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
|
||||
}
|
||||
}
|
||||
@ -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
@ -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 {
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -268,6 +268,7 @@ module TypeScript {
|
||||
Parameter,
|
||||
EnumElement,
|
||||
TypeAnnotation,
|
||||
ExpressionBody,
|
||||
ComputedPropertyName,
|
||||
ExternalModuleReference,
|
||||
ModuleNameModuleReference,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 ""; }
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
296
src/services/text.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
}
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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'.
|
||||
@ -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.
|
||||
@ -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.
|
||||
@ -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'.
|
||||
@ -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'.
|
||||
@ -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'.
|
||||
@ -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'.
|
||||
@ -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'.
|
||||
@ -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'.
|
||||
@ -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.
|
||||
}
|
||||
@ -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.
|
||||
}
|
||||
@ -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'.
|
||||
}
|
||||
8
tests/baselines/reference/FunctionDeclaration10_es6.js
Normal file
8
tests/baselines/reference/FunctionDeclaration10_es6.js
Normal 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; }; }
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
7
tests/baselines/reference/FunctionDeclaration11_es6.js
Normal file
7
tests/baselines/reference/FunctionDeclaration11_es6.js
Normal file
@ -0,0 +1,7 @@
|
||||
//// [FunctionDeclaration11_es6.ts]
|
||||
function * yield() {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration11_es6.js]
|
||||
function yield() {
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts ===
|
||||
function * yield() {
|
||||
>yield : () => void
|
||||
}
|
||||
@ -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.
|
||||
@ -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'.
|
||||
}
|
||||
|
||||
12
tests/baselines/reference/FunctionDeclaration13_es6.js
Normal file
12
tests/baselines/reference/FunctionDeclaration13_es6.js
Normal 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;
|
||||
}
|
||||
7
tests/baselines/reference/FunctionDeclaration1_es6.js
Normal file
7
tests/baselines/reference/FunctionDeclaration1_es6.js
Normal file
@ -0,0 +1,7 @@
|
||||
//// [FunctionDeclaration1_es6.ts]
|
||||
function * foo() {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration1_es6.js]
|
||||
function foo() {
|
||||
}
|
||||
4
tests/baselines/reference/FunctionDeclaration1_es6.types
Normal file
4
tests/baselines/reference/FunctionDeclaration1_es6.types
Normal file
@ -0,0 +1,4 @@
|
||||
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts ===
|
||||
function * foo() {
|
||||
>foo : () => void
|
||||
}
|
||||
7
tests/baselines/reference/FunctionDeclaration2_es6.js
Normal file
7
tests/baselines/reference/FunctionDeclaration2_es6.js
Normal file
@ -0,0 +1,7 @@
|
||||
//// [FunctionDeclaration2_es6.ts]
|
||||
function f(yield) {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration2_es6.js]
|
||||
function f(yield) {
|
||||
}
|
||||
5
tests/baselines/reference/FunctionDeclaration2_es6.types
Normal file
5
tests/baselines/reference/FunctionDeclaration2_es6.types
Normal file
@ -0,0 +1,5 @@
|
||||
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration2_es6.ts ===
|
||||
function f(yield) {
|
||||
>f : (yield: any) => void
|
||||
>yield : any
|
||||
}
|
||||
@ -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.
|
||||
}
|
||||
8
tests/baselines/reference/FunctionDeclaration3_es6.js
Normal file
8
tests/baselines/reference/FunctionDeclaration3_es6.js
Normal file
@ -0,0 +1,8 @@
|
||||
//// [FunctionDeclaration3_es6.ts]
|
||||
function f(yield = yield) {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration3_es6.js]
|
||||
function f(yield) {
|
||||
if (yield === void 0) { yield = yield; }
|
||||
}
|
||||
7
tests/baselines/reference/FunctionDeclaration4_es6.js
Normal file
7
tests/baselines/reference/FunctionDeclaration4_es6.js
Normal file
@ -0,0 +1,7 @@
|
||||
//// [FunctionDeclaration4_es6.ts]
|
||||
function yield() {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration4_es6.js]
|
||||
function yield() {
|
||||
}
|
||||
4
tests/baselines/reference/FunctionDeclaration4_es6.types
Normal file
4
tests/baselines/reference/FunctionDeclaration4_es6.types
Normal file
@ -0,0 +1,4 @@
|
||||
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration4_es6.ts ===
|
||||
function yield() {
|
||||
>yield : () => void
|
||||
}
|
||||
@ -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'.
|
||||
}
|
||||
@ -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'.
|
||||
}
|
||||
8
tests/baselines/reference/FunctionDeclaration6_es6.js
Normal file
8
tests/baselines/reference/FunctionDeclaration6_es6.js
Normal file
@ -0,0 +1,8 @@
|
||||
//// [FunctionDeclaration6_es6.ts]
|
||||
function*foo(a = yield) {
|
||||
}
|
||||
|
||||
//// [FunctionDeclaration6_es6.js]
|
||||
function foo(a) {
|
||||
if (a === void 0) { a = yield; }
|
||||
}
|
||||
@ -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'.
|
||||
}
|
||||
}
|
||||
14
tests/baselines/reference/FunctionDeclaration7_es6.js
Normal file
14
tests/baselines/reference/FunctionDeclaration7_es6.js
Normal 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; }
|
||||
}
|
||||
}
|
||||
@ -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'.
|
||||
@ -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.
|
||||
6
tests/baselines/reference/FunctionExpression1_es6.js
Normal file
6
tests/baselines/reference/FunctionExpression1_es6.js
Normal file
@ -0,0 +1,6 @@
|
||||
//// [FunctionExpression1_es6.ts]
|
||||
var v = function * () { }
|
||||
|
||||
//// [FunctionExpression1_es6.js]
|
||||
var v = function () {
|
||||
};
|
||||
5
tests/baselines/reference/FunctionExpression1_es6.types
Normal file
5
tests/baselines/reference/FunctionExpression1_es6.types
Normal 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
Loading…
x
Reference in New Issue
Block a user