This commit is contained in:
Yui T 2014-11-25 10:30:20 -08:00
commit 44e6bcf7ff
248 changed files with 3507 additions and 1287 deletions

View File

@ -125,6 +125,7 @@ module ts {
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." },

View File

@ -491,6 +491,10 @@
"category": "Error",
"code": 1162
},
"'yield' expression must be contained_within a generator declaration.": {
"category": "Error",
"code": 1163
},
"Duplicate identifier '{0}'.": {
"category": "Error",

File diff suppressed because it is too large Load Diff

View File

@ -183,6 +183,7 @@ module ts {
ConditionalExpression,
TemplateExpression,
TemplateSpan,
YieldExpression,
OmittedExpression,
// Element
Block,
@ -269,20 +270,30 @@ module ts {
DeclarationFile = 0x00000400, // Node is a .d.ts file
Let = 0x00000800, // Variable declaration
Const = 0x00001000, // Variable declaration
// 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.
ParsedInStrictMode = 0x00002000,
OctalLiteral = 0x00004000,
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)
@ -429,6 +440,10 @@ module ts {
operator: SyntaxKind;
operand: Expression;
}
export interface YieldExpression extends Expression {
expression: Expression;
}
export interface BinaryExpression extends Expression {
left: Expression;
@ -758,7 +773,7 @@ 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;

View File

@ -3887,39 +3887,56 @@ module ts {
var searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
// Get the text to search for, we need to normalize it as external module names will have quote
var symbolName = getNormalizedSymbolName(symbol.name, declarations);
var declaredName = getDeclaredName(symbol);
// Get syntactic diagnostics
// Try to get the smallest valid scope that we can limit our search to;
// otherwise we'll need to search globally (i.e. include each file).
var scope = getSymbolScope(symbol);
if (scope) {
result = [];
getReferencesInNode(scope, symbol, symbolName, node, searchMeaning, findInStrings, findInComments, result);
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
}
else {
var internedName = getInternedName(symbol, declarations)
forEach(sourceFiles, sourceFile => {
cancellationToken.throwIfCancellationRequested();
if (lookUp(sourceFile.identifiers, symbolName)) {
if (lookUp(sourceFile.identifiers, internedName)) {
result = result || [];
getReferencesInNode(sourceFile, symbol, symbolName, node, searchMeaning, findInStrings, findInComments, result);
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result);
}
});
}
return result;
function getNormalizedSymbolName(symbolName: string, declarations: Declaration[]): string {
function getDeclaredName(symbol: Symbol) {
var name = typeInfoResolver.symbolToString(symbol);
return stripQuotes(name);
}
function getInternedName(symbol: Symbol, declarations: Declaration[]): string {
// Special case for function expressions, whose names are solely local to their bodies.
var functionExpression = forEach(declarations, d => d.kind === SyntaxKind.FunctionExpression ? <FunctionExpression>d : undefined);
// When a name gets interned into a SourceFile's 'identifiers' Map,
// its name is escaped and stored in the same way its symbol name/identifier
// name should be stored. Function expressions, however, are a special case,
// because despite sometimes having a name, the binder unconditionally binds them
// to a symbol with the name "__function".
if (functionExpression && functionExpression.name) {
var name = functionExpression.name.text;
}
else {
var name = symbolName;
var name = symbol.name;
}
return stripQuotes(name);
}
function stripQuotes(name: string) {
var length = name.length;
if (length >= 2 && name.charCodeAt(0) === CharacterCodes.doubleQuote && name.charCodeAt(length - 1) === CharacterCodes.doubleQuote) {
return name.substring(1, length - 1);
@ -5385,7 +5402,7 @@ module ts {
getFormattingEditsForDocument,
getFormattingEditsAfterKeystroke,
getEmitOutput,
getSourceFile: getCurrentSourceFile,
getSourceFile: getCurrentSourceFile,
};
}

View File

@ -164,6 +164,20 @@ module ts.SignatureHelp {
//}
var emptyArray: any[] = [];
const enum ArgumentListKind {
TypeArguments,
CallArguments,
TaggedTemplateArguments
}
interface ArgumentListInfo {
kind: ArgumentListKind;
invocation: CallLikeExpression;
argumentsSpan: TextSpan;
argumentIndex?: number;
argumentCount: number;
}
export function getSignatureHelpItems(sourceFile: SourceFile, position: number, typeInfoResolver: TypeChecker, cancellationToken: CancellationTokenObject): SignatureHelpItems {
// Decide whether to show signature help
var startingToken = findTokenOnLeftOfPosition(sourceFile, position);
@ -180,7 +194,7 @@ module ts.SignatureHelp {
return undefined;
}
var call = <CallExpression>argumentInfo.list.parent;
var call = argumentInfo.invocation;
var candidates = <Signature[]>[];
var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates);
cancellationToken.throwIfCancellationRequested();
@ -192,50 +206,195 @@ module ts.SignatureHelp {
return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
/**
* If node is an argument, returns its index in the argument list.
* If not, returns -1.
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
function getImmediatelyContainingArgumentInfo(node: Node): ListItemInfo {
if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) {
return undefined;
}
function getImmediatelyContainingArgumentInfo(node: Node): ArgumentListInfo {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
var callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo#o<T, U>#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken ||
node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
var isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
Debug.assert(list !== undefined);
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list),
argumentIndex: 0,
argumentCount: getCommaBasedArgCount(list)
};
}
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<$T, U>($a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo$o<T, U>$(a, b)$ -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T$, U$>(a$, $b$) -> The token is buried inside a list, and should give sig help
var parent = <CallExpression>node.parent;
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
var list = getChildListThatStartsWithOpenerToken(parent, node, sourceFile);
Debug.assert(list !== undefined);
return {
list,
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,14 +451,13 @@ 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[];
@ -310,27 +468,28 @@ module ts.SignatureHelp {
prefixDisplayParts.push.apply(prefixDisplayParts, callTargetDisplayParts);
}
if (isTypeParameterHelp) {
if (isTypeParameterList) {
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
var typeParameters = candidateSignature.typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
var parameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, argumentListOrTypeArgumentList));
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, invocation));
suffixDisplayParts.push.apply(suffixDisplayParts, parameterParts);
}
else {
var typeParameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, argumentListOrTypeArgumentList));
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;
suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
var returnTypeParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, argumentListOrTypeArgumentList));
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
suffixDisplayParts.push.apply(suffixDisplayParts, returnTypeParts);
return {
@ -343,34 +502,10 @@ module ts.SignatureHelp {
};
});
// 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 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) {
@ -387,7 +522,7 @@ module ts.SignatureHelp {
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);
@ -401,7 +536,7 @@ module ts.SignatureHelp {
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,

View File

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

File diff suppressed because one or more lines are too long

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1430,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;
@ -1449,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;
@ -1489,11 +1479,6 @@ module TypeScript.Scanner {
return undefined;
}
function consumeNode(node: ISyntaxNode): void {
// Should never get called.
throw Errors.invalidOperation();
}
function absolutePosition() {
return _absolutePosition;
}
@ -1561,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 {
@ -1644,15 +1636,13 @@ module TypeScript.Scanner {
currentToken: currentToken,
currentContextualToken: currentContextualToken,
peekToken: peekToken,
consumeNode: consumeNode,
consumeToken: consumeToken,
consumeNodeOrToken: consumeNodeOrToken,
getRewindPoint: getRewindPoint,
rewind: rewind,
releaseRewindPoint: releaseRewindPoint,
tokenDiagnostics: tokenDiagnostics,
release: release,
absolutePosition: absolutePosition,
resetToPosition: resetToPosition,
};
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -320,4 +320,9 @@ module ts {
export function isPunctuation(kind: SyntaxKind): boolean {
return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation;
}
export function isInsideTemplateLiteral(node: LiteralExpression, position: number) {
return (node.getStart() < position && position < node.getEnd())
|| (isUnterminatedTemplateEnd(node) && position === node.getEnd());
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,7 @@
=== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts ===
var v = { *foo() { } }
>v : { foo: () => void; }
>{ *foo() { } } : { foo: () => void; }
>foo : () => void
>*foo() { } : () => void

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments2_es6.ts(1,12): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments2_es6.ts (1 errors) ====
var v = { *() { } }
~
!!! error TS1003: Identifier expected.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments3_es6.ts(1,12): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments3_es6.ts (1 errors) ====
var v = { *{ } }
~
!!! error TS1003: Identifier expected.

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments4_es6.ts(1,13): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments4_es6.ts (1 errors) ====
var v = { * }
~
!!! error TS1003: Identifier expected.

View File

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

View File

@ -0,0 +1,7 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments6_es6.ts(1,12): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments6_es6.ts (1 errors) ====
var v = { *<T>() { } }
~
!!! error TS1003: Identifier expected.

View File

@ -0,0 +1,13 @@
//// [MemberFunctionDeclaration1_es6.ts]
class C {
*foo() { }
}
//// [MemberFunctionDeclaration1_es6.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
};
return C;
})();

View File

@ -0,0 +1,7 @@
=== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts ===
class C {
>C : C
*foo() { }
>foo : () => void
}

View File

@ -0,0 +1,13 @@
//// [MemberFunctionDeclaration2_es6.ts]
class C {
public * foo() { }
}
//// [MemberFunctionDeclaration2_es6.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
};
return C;
})();

View File

@ -0,0 +1,7 @@
=== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts ===
class C {
>C : C
public * foo() { }
>foo : () => void
}

View File

@ -0,0 +1,18 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,5): error TS1003: Identifier expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,10): error TS1005: ';' expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,13): error TS1005: '=>' expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(3,1): error TS1128: Declaration or statement expected.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts (4 errors) ====
class C {
*[foo]() { }
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: ';' expected.
~
!!! error TS1005: '=>' expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration4_es6.ts(2,5): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration4_es6.ts (1 errors) ====
class C {
*() { }
~
!!! error TS1003: Identifier expected.
}

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration5_es6.ts(3,1): error TS1003: Identifier expected.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration5_es6.ts (1 errors) ====
class C {
*
}
~
!!! error TS1003: Identifier expected.

View File

@ -0,0 +1,12 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration6_es6.ts(3,1): error TS1005: '(' expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration6_es6.ts(2,5): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration6_es6.ts (2 errors) ====
class C {
*foo
~~~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
}
~
!!! error TS1005: '(' expected.

View File

@ -0,0 +1,13 @@
//// [MemberFunctionDeclaration7_es6.ts]
class C {
*foo<T>() { }
}
//// [MemberFunctionDeclaration7_es6.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
};
return C;
})();

View File

@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts ===
class C {
>C : C
*foo<T>() { }
>foo : <T>() => void
>T : T
}

View File

@ -0,0 +1,34 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(4,12): error TS1127: Invalid character.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(4,14): error TS1129: Statement expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(4,19): error TS1005: '(' expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(5,5): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(6,3): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(7,1): error TS1128: Declaration or statement expected.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(4,9): error TS2304: Cannot find name 'a'.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts(4,16): error TS2391: Function implementation is missing or not immediately following the declaration.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration8_es6.ts (8 errors) ====
class C {
foo() {
// Make sure we don't think of *bar as the start of a generator method.
if (a) # * bar;
!!! error TS1127: Invalid character.
~
!!! error TS1129: Statement expected.
~
!!! error TS1005: '(' expected.
~
!!! error TS2304: Cannot find name 'a'.
~~~
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
return bar;
~~~~~~
!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
}
~
!!! error TS1128: Declaration or statement expected.
}
~
!!! error TS1128: Declaration or statement expected.

View File

@ -0,0 +1,10 @@
tests/cases/conformance/es6/templates/TemplateExpression1.ts(1,19): error TS1158: Invalid template literal; expected '}'
tests/cases/conformance/es6/templates/TemplateExpression1.ts(1,17): error TS2304: Cannot find name 'a'.
==== tests/cases/conformance/es6/templates/TemplateExpression1.ts (2 errors) ====
var v = `foo ${ a
!!! error TS1158: Invalid template literal; expected '}'
~
!!! error TS2304: Cannot find name 'a'.

View File

@ -0,0 +1,11 @@
//// [YieldExpression10_es6.ts]
var v = { * foo() {
yield(foo);
}
}
//// [YieldExpression10_es6.js]
var v = { foo: function () {
;
} };

View File

@ -0,0 +1,11 @@
=== tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts ===
var v = { * foo() {
>v : { foo: () => void; }
>{ * foo() { yield(foo); }} : { foo: () => void; }
>foo : () => void
>* foo() { yield(foo); } : () => void
yield(foo);
}
}

View File

@ -0,0 +1,16 @@
//// [YieldExpression11_es6.ts]
class C {
*foo() {
yield(foo);
}
}
//// [YieldExpression11_es6.js]
var C = (function () {
function C() {
}
C.prototype.foo = function () {
;
};
return C;
})();

View File

@ -0,0 +1,10 @@
=== tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts ===
class C {
>C : C
*foo() {
>foo : () => void
yield(foo);
}
}

View File

@ -0,0 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression12_es6.ts(3,6): error TS1163: 'yield' expression must be contained_within a generator declaration.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression12_es6.ts (1 errors) ====
class C {
constructor() {
yield foo
~~~~~
!!! error TS1163: 'yield' expression must be contained_within a generator declaration.
}
}

View File

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

View File

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

View File

@ -0,0 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression14_es6.ts(3,6): error TS1163: 'yield' expression must be contained_within a generator declaration.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression14_es6.ts (1 errors) ====
class C {
foo() {
yield foo
~~~~~
!!! error TS1163: 'yield' expression must be contained_within a generator declaration.
}
}

View File

@ -0,0 +1,9 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression15_es6.ts(2,6): error TS1163: 'yield' expression must be contained_within a generator declaration.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression15_es6.ts (1 errors) ====
var v = () => {
yield foo
~~~~~
!!! error TS1163: 'yield' expression must be contained_within a generator declaration.
}

View File

@ -0,0 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(3,5): error TS1163: 'yield' expression must be contained_within a generator declaration.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts (1 errors) ====
function* foo() {
function bar() {
yield foo;
~~~~~
!!! error TS1163: 'yield' expression must be contained_within a generator declaration.
}
}

View File

@ -0,0 +1,10 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression17_es6.ts(1,15): error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression17_es6.ts(1,15): error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression17_es6.ts (2 errors) ====
var v = { get foo() { yield foo; } }
~~~
!!! error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
~~~
!!! error TS2378: A 'get' accessor must return a value or consist of a single 'throw' statement.

View File

@ -0,0 +1,8 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression18_es6.ts(2,1): error TS1163: 'yield' expression must be contained_within a generator declaration.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression18_es6.ts (1 errors) ====
"use strict";
yield(foo);
~~~~~
!!! error TS1163: 'yield' expression must be contained_within a generator declaration.

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