Merge branch 'master' into sourceFileUpdate
Conflicts: src/compiler/parser.ts src/compiler/types.ts src/compiler/utilities.ts
This commit is contained in:
commit
760eb9b8e0
6 changed files with 195 additions and 184 deletions
|
@ -1335,7 +1335,7 @@ module ts {
|
|||
// flag so that we don't mark any subsequent nodes.
|
||||
if (parseErrorBeforeNextFinishedNode) {
|
||||
parseErrorBeforeNextFinishedNode = false;
|
||||
node.flags |= NodeFlags.ContainsError;
|
||||
node.parserContextFlags |= ParserContextFlags.ThisNodeHasError;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -1701,7 +1701,7 @@ module ts {
|
|||
// differently depending on what mode it is in.
|
||||
//
|
||||
// This also applies to all our other context flags as well.
|
||||
var nodeContextFlags = node.parserContextFlags & ParserContextFlags.FlagsMask;
|
||||
var nodeContextFlags = node.parserContextFlags & ParserContextFlags.ParserGeneratedFlags;
|
||||
if (nodeContextFlags !== contextFlags) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -3941,27 +3941,25 @@ module ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function isLabel(): boolean {
|
||||
return isIdentifier() && lookAhead(nextTokenIsColonToken);
|
||||
}
|
||||
function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement {
|
||||
// Avoiding having to do the lookahead for a labeled statement by just trying to parse
|
||||
// out an expression, seeing if it is identifier and then seeing if it is followed by
|
||||
// a colon.
|
||||
var fullStart = scanner.getStartPos();
|
||||
var expression = allowInAnd(parseExpression);
|
||||
|
||||
function nextTokenIsColonToken() {
|
||||
return nextToken() === SyntaxKind.ColonToken;
|
||||
}
|
||||
|
||||
function parseLabeledStatement(): LabeledStatement {
|
||||
var node = <LabeledStatement>createNode(SyntaxKind.LabeledStatement);
|
||||
node.label = parseIdentifier();
|
||||
parseExpected(SyntaxKind.ColonToken);
|
||||
node.statement = parseStatement();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseExpressionStatement(): ExpressionStatement {
|
||||
var node = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement);
|
||||
node.expression = allowInAnd(parseExpression);
|
||||
parseSemicolon();
|
||||
return finishNode(node);
|
||||
if (expression.kind === SyntaxKind.Identifier && parseOptional(SyntaxKind.ColonToken)) {
|
||||
var labeledStatement = <LabeledStatement>createNode(SyntaxKind.LabeledStatement, fullStart);
|
||||
labeledStatement.label = <Identifier>expression;
|
||||
labeledStatement.statement = parseStatement();
|
||||
return finishNode(labeledStatement);
|
||||
}
|
||||
else {
|
||||
var expressionStatement = <ExpressionStatement>createNode(SyntaxKind.ExpressionStatement, fullStart);
|
||||
expressionStatement.expression = expression;
|
||||
parseSemicolon();
|
||||
return finishNode(expressionStatement);
|
||||
}
|
||||
}
|
||||
|
||||
function isStartOfStatement(inErrorRecovery: boolean): boolean {
|
||||
|
@ -4107,9 +4105,7 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
return isLabel()
|
||||
? parseLabeledStatement()
|
||||
: parseExpressionStatement();
|
||||
return parseExpressionOrLabeledStatement();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -294,17 +294,6 @@ module ts {
|
|||
Const = 0x00001000, // Variable declaration
|
||||
OctalLiteral = 0x00002000,
|
||||
|
||||
// If the parser encountered an error when parsing the code that created this node. Note
|
||||
// the parser only sets this directly on the node it creates right after encountering the
|
||||
// error. We then propagate that flag upwards to parent nodes during incremental parsing.
|
||||
ContainsError = 0x00004000,
|
||||
|
||||
// Used during incremental parsing to determine if we need to visit this node to see if
|
||||
// any of its children had an error. Once we compute that once, we can set this bit on the
|
||||
// node to know that we never have to do it again. From that point on, we can just check
|
||||
// the node directly for 'ContainsError'.
|
||||
HasPropagatedChildContainsErrorFlag = 0x00008000,
|
||||
|
||||
Modifier = Export | Ambient | Public | Private | Protected | Static,
|
||||
AccessibilityModifier = Public | Private | Protected,
|
||||
BlockScoped = Let | Const
|
||||
|
@ -324,7 +313,24 @@ module ts {
|
|||
// If this node was parsed in the parameters of a generator.
|
||||
GeneratorParameter = 1 << 3,
|
||||
|
||||
FlagsMask = StrictMode | DisallowIn | Yield | GeneratorParameter,
|
||||
// If the parser encountered an error when parsing the code that created this node. Note
|
||||
// the parser only sets this directly on the node it creates right after encountering the
|
||||
// error.
|
||||
ThisNodeHasError = 1 << 4,
|
||||
|
||||
// Context flags set directly by the parser.
|
||||
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | ThisNodeHasError,
|
||||
|
||||
// Context flags computed by aggregating child flags upwards.
|
||||
|
||||
// If this node, or any of it's children (transitively) contain an error.
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 5,
|
||||
|
||||
// Used during incremental parsing to determine if we need to visit this node to see if
|
||||
// any of its children had an error. Once we compute that once, we can set this bit on the
|
||||
// node to know that we never have to do it again. From that point on, we can just check
|
||||
// the node directly for 'ContainsError'.
|
||||
HasComputedThisNodeOrAnySubNodesHasError = 1 << 6
|
||||
}
|
||||
|
||||
export interface Node extends TextRange {
|
||||
|
|
|
@ -68,25 +68,25 @@ module ts {
|
|||
|
||||
// Returns true if this node contains a parse error anywhere underneath it.
|
||||
export function containsParseError(node: Node): boolean {
|
||||
if (!hasFlag(node.flags, NodeFlags.HasPropagatedChildContainsErrorFlag)) {
|
||||
if (!hasFlag(node.parserContextFlags, ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError)) {
|
||||
// A node is considered to contain a parse error if:
|
||||
// a) the parser explicitly marked that it had an error
|
||||
// b) any of it's children reported that it had an error.
|
||||
var val = hasFlag(node.flags, NodeFlags.ContainsError) ||
|
||||
var val = hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeHasError) ||
|
||||
forEachChild(node, containsParseError);
|
||||
|
||||
// If so, mark ourselves accordingly.
|
||||
if (val) {
|
||||
node.flags |= NodeFlags.ContainsError;
|
||||
node.parserContextFlags |= ParserContextFlags.ThisNodeOrAnySubNodesHasError;
|
||||
}
|
||||
|
||||
// Also mark that we've propogated the child information to this node. This way we can
|
||||
// always consult the bit directly on this node without needing to check its children
|
||||
// again.
|
||||
node.flags |= NodeFlags.HasPropagatedChildContainsErrorFlag;
|
||||
node.parserContextFlags |= ParserContextFlags.HasComputedThisNodeOrAnySubNodesHasError;
|
||||
}
|
||||
|
||||
return hasFlag(node.flags, NodeFlags.ContainsError);
|
||||
return hasFlag(node.parserContextFlags, ParserContextFlags.ThisNodeOrAnySubNodesHasError);
|
||||
}
|
||||
|
||||
export function getSourceFileOfNode(node: Node): SourceFile {
|
||||
|
|
|
@ -1415,44 +1415,50 @@ module FourSlash {
|
|||
}
|
||||
|
||||
private checkPostEditInvariants() {
|
||||
return;
|
||||
if (this.editValidation === IncrementalEditValidation.None) {
|
||||
return;
|
||||
}
|
||||
|
||||
/// TODO: reimplement this section
|
||||
//if (this.editValidation === IncrementalEditValidation.None) {
|
||||
// return;
|
||||
//}
|
||||
var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName);
|
||||
var incrementalSyntaxDiagnostics = JSON.stringify(Utils.convertDiagnostics(incrementalSourceFile.getSyntacticDiagnostics()));
|
||||
|
||||
//// Get syntactic errors (to force a refresh)
|
||||
//var incrSyntaxErrs = JSON.stringify(this.languageService.getSyntacticDiagnostics(this.activeFile.fileName));
|
||||
// Check syntactic structure
|
||||
var snapshot = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName);
|
||||
var content = snapshot.getText(0, snapshot.getLength());
|
||||
|
||||
//// Check syntactic structure
|
||||
//var snapshot = this.languageServiceShimHost.getScriptSnapshot(this.activeFile.fileName);
|
||||
//var content = snapshot.getText(0, snapshot.getLength());
|
||||
//var refSyntaxTree = TypeScript.Parser.parse(this.activeFile.fileName, TypeScript.SimpleText.fromString(content), ts.ScriptTarget.ES5, TypeScript.isDTSFile(this.activeFile.fileName));
|
||||
//var fullSyntaxErrs = JSON.stringify(refSyntaxTree.diagnostics());
|
||||
var referenceSourceFile = ts.createLanguageServiceSourceFile(
|
||||
this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*isOpen:*/ false, /*setNodeParents:*/ false);
|
||||
var referenceSyntaxDiagnostics = JSON.stringify(Utils.convertDiagnostics(referenceSourceFile.getSyntacticDiagnostics()));
|
||||
|
||||
//if (incrSyntaxErrs !== fullSyntaxErrs) {
|
||||
// this.raiseError('Mismatched incremental/full syntactic errors for file ' + this.activeFile.fileName + '.\n=== Incremental errors ===\n' + incrSyntaxErrs + '\n=== Full Errors ===\n' + fullSyntaxErrs);
|
||||
//}
|
||||
if (incrementalSyntaxDiagnostics !== referenceSyntaxDiagnostics) {
|
||||
this.raiseError('Mismatched incremental/reference syntactic diagnostics for file ' + this.activeFile.fileName + '.\n=== Incremental diagnostics ===\n' + incrementalSyntaxDiagnostics + '\n=== Reference Diagnostics ===\n' + referenceSyntaxDiagnostics);
|
||||
}
|
||||
|
||||
// if (this.editValidation !== IncrementalEditValidation.SyntacticOnly) {
|
||||
// var compiler = new TypeScript.TypeScriptCompiler();
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// snapshot = this.languageServiceShimHost.getScriptSnapshot(this.testData.files[i].fileName);
|
||||
// compiler.addFile(this.testData.files[i].fileName, TypeScript.ScriptSnapshot.fromString(snapshot.getText(0, snapshot.getLength())), ts.ByteOrderMark.None, 0, true);
|
||||
// }
|
||||
var incrementalSourceFileJSON = Utils.sourceFileToJSON(incrementalSourceFile);
|
||||
var referenceSourceFileJSON = Utils.sourceFileToJSON(referenceSourceFile);
|
||||
|
||||
// compiler.addFile('lib.d.ts', TypeScript.ScriptSnapshot.fromString(Harness.Compiler.libTextMinimal), ts.ByteOrderMark.None, 0, true);
|
||||
if (incrementalSyntaxDiagnostics !== referenceSyntaxDiagnostics) {
|
||||
this.raiseError('Mismatched incremental/reference ast for file ' + this.activeFile.fileName + '.\n=== Incremental AST ===\n' + incrementalSourceFileJSON + '\n=== Reference AST ===\n' + referenceSourceFileJSON);
|
||||
}
|
||||
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// var refSemanticErrs = JSON.stringify(compiler.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
// var incrSemanticErrs = JSON.stringify(this.languageService.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
//if (this.editValidation !== IncrementalEditValidation.SyntacticOnly) {
|
||||
// var compiler = new TypeScript.TypeScriptCompiler();
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// snapshot = this.languageServiceShimHost.getScriptSnapshot(this.testData.files[i].fileName);
|
||||
// compiler.addFile(this.testData.files[i].fileName, TypeScript.ScriptSnapshot.fromString(snapshot.getText(0, snapshot.getLength())), ts.ByteOrderMark.None, 0, true);
|
||||
// }
|
||||
|
||||
// if (incrSemanticErrs !== refSemanticErrs) {
|
||||
// this.raiseError('Mismatched incremental/full semantic errors for file ' + this.testData.files[i].fileName + '\n=== Incremental errors ===\n' + incrSemanticErrs + '\n=== Full Errors ===\n' + refSemanticErrs);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// compiler.addFile('lib.d.ts', TypeScript.ScriptSnapshot.fromString(Harness.Compiler.libTextMinimal), ts.ByteOrderMark.None, 0, true);
|
||||
|
||||
// for (var i = 0; i < this.testData.files.length; i++) {
|
||||
// var refSemanticErrs = JSON.stringify(compiler.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
// var incrSemanticErrs = JSON.stringify(this.languageService.getSemanticDiagnostics(this.testData.files[i].fileName));
|
||||
|
||||
// if (incrSemanticErrs !== refSemanticErrs) {
|
||||
// this.raiseError('Mismatched incremental/full semantic errors for file ' + this.testData.files[i].fileName + '\n=== Incremental errors ===\n' + incrSemanticErrs + '\n=== Full Errors ===\n' + refSemanticErrs);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
private fixCaretPosition() {
|
||||
|
|
|
@ -175,6 +175,120 @@ module Utils {
|
|||
function isNodeOrArray(a: any): boolean {
|
||||
return a !== undefined && typeof a.pos === "number";
|
||||
}
|
||||
|
||||
export function convertDiagnostics(diagnostics: ts.Diagnostic[]) {
|
||||
return diagnostics.map(convertDiagnostic);
|
||||
}
|
||||
|
||||
function convertDiagnostic(diagnostic: ts.Diagnostic) {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
messageText: diagnostic.messageText,
|
||||
category: (<any>ts).DiagnosticCategory[diagnostic.category],
|
||||
code: diagnostic.code
|
||||
};
|
||||
}
|
||||
|
||||
export function sourceFileToJSON(file: ts.SourceFile): string {
|
||||
return JSON.stringify(file,(k, v) => {
|
||||
return isNodeOrArray(v) ? serializeNode(v) : v;
|
||||
}, " ");
|
||||
|
||||
function getKindName(k: number): string {
|
||||
return (<any>ts).SyntaxKind[k]
|
||||
}
|
||||
|
||||
function getFlagName(flags: any, f: number): any {
|
||||
if (f === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var result = "";
|
||||
ts.forEach(Object.getOwnPropertyNames(flags),(v: any) => {
|
||||
if (isFinite(v)) {
|
||||
v = +v;
|
||||
if (f === +v) {
|
||||
result = flags[v];
|
||||
return true;
|
||||
}
|
||||
else if ((f & v) > 0) {
|
||||
if (result.length)
|
||||
result += " | ";
|
||||
result += flags[v];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getNodeFlagName(f: number) { return getFlagName((<any>ts).NodeFlags, f); }
|
||||
function getParserContextFlagName(f: number) {
|
||||
// Clear the flag that are produced by aggregating child values.. That is ephemeral
|
||||
// data we don't care about in the dump. We only care what the parser set directly
|
||||
// on the ast.
|
||||
return getFlagName((<any>ts).ParserContextFlags, f & ts.ParserContextFlags.ParserGeneratedFlags);
|
||||
}
|
||||
|
||||
function serializeNode(n: ts.Node): any {
|
||||
var o: any = { kind: getKindName(n.kind) };
|
||||
o.containsParseError = ts.containsParseError(n);
|
||||
|
||||
ts.forEach(Object.getOwnPropertyNames(n), propertyName => {
|
||||
switch (propertyName) {
|
||||
case "parent":
|
||||
case "symbol":
|
||||
case "locals":
|
||||
case "localSymbol":
|
||||
case "kind":
|
||||
case "semanticDiagnostics":
|
||||
case "id":
|
||||
case "nodeCount":
|
||||
case "symbolCount":
|
||||
case "identifierCount":
|
||||
case "scriptSnapshot":
|
||||
// Blacklist of items we never put in the baseline file.
|
||||
break;
|
||||
|
||||
case "flags":
|
||||
// Print out flags with their enum names.
|
||||
o[propertyName] = getNodeFlagName(n.flags);
|
||||
break;
|
||||
|
||||
case "parserContextFlags":
|
||||
o[propertyName] = getParserContextFlagName(n.parserContextFlags);
|
||||
break;
|
||||
|
||||
case "referenceDiagnostics":
|
||||
case "parseDiagnostics":
|
||||
case "grammarDiagnostics":
|
||||
o[propertyName] = Utils.convertDiagnostics((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "nextContainer":
|
||||
if (n.nextContainer) {
|
||||
o[propertyName] = { kind: n.nextContainer.kind, pos: n.nextContainer.pos, end: n.nextContainer.end };
|
||||
}
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// Include 'text' field for identifiers/literals, but not for source files.
|
||||
if (n.kind !== ts.SyntaxKind.SourceFile) {
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Harness.Path {
|
||||
|
|
|
@ -21,117 +21,6 @@ class Test262BaselineRunner extends RunnerBase {
|
|||
return Test262BaselineRunner.basePath + "/" + filename;
|
||||
}
|
||||
|
||||
private static serializeSourceFile(file: ts.SourceFile): string {
|
||||
function getKindName(k: number): string {
|
||||
return (<any>ts).SyntaxKind[k]
|
||||
}
|
||||
|
||||
function getFlagName(flags: any, f: number): any {
|
||||
if (f === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var result = "";
|
||||
ts.forEach(Object.getOwnPropertyNames(flags), (v: any) => {
|
||||
if (isFinite(v)) {
|
||||
v = +v;
|
||||
if (f === +v) {
|
||||
result = flags[v];
|
||||
return true;
|
||||
}
|
||||
else if ((f & v) > 0) {
|
||||
if (result.length)
|
||||
result += " | ";
|
||||
result += flags[v];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getNodeFlagName(f: number) { return getFlagName((<any>ts).NodeFlags, f); }
|
||||
function getParserContextFlagName(f: number) { return getFlagName((<any>ts).ParserContextFlags, f); }
|
||||
function convertDiagnostics(diagnostics: ts.Diagnostic[]) {
|
||||
return diagnostics.map(convertDiagnostic);
|
||||
}
|
||||
|
||||
function convertDiagnostic(diagnostic: ts.Diagnostic): any {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
messageText: diagnostic.messageText,
|
||||
category: (<any>ts).DiagnosticCategory[diagnostic.category],
|
||||
code: diagnostic.code
|
||||
};
|
||||
}
|
||||
|
||||
function serializeNode(n: ts.Node): any {
|
||||
var o: any = { kind: getKindName(n.kind) };
|
||||
o.containsParseError = ts.containsParseError(n);
|
||||
|
||||
ts.forEach(Object.getOwnPropertyNames(n), propertyName => {
|
||||
switch (propertyName) {
|
||||
case "parent":
|
||||
case "symbol":
|
||||
case "locals":
|
||||
case "localSymbol":
|
||||
case "kind":
|
||||
case "semanticDiagnostics":
|
||||
case "id":
|
||||
case "nodeCount":
|
||||
case "symbolCount":
|
||||
case "identifierCount":
|
||||
// Blacklist of items we never put in the baseline file.
|
||||
break;
|
||||
|
||||
case "flags":
|
||||
// Print out flags with their enum names.
|
||||
o[propertyName] = getNodeFlagName(n.flags);
|
||||
break;
|
||||
|
||||
case "parserContextFlags":
|
||||
o[propertyName] = getParserContextFlagName(n.parserContextFlags);
|
||||
break;
|
||||
|
||||
case "referenceDiagnostics":
|
||||
case "parseDiagnostics":
|
||||
case "grammarDiagnostics":
|
||||
o[propertyName] = convertDiagnostics((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "nextContainer":
|
||||
if (n.nextContainer) {
|
||||
o[propertyName] = { kind: n.nextContainer.kind, pos: n.nextContainer.pos, end: n.nextContainer.end };
|
||||
}
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// Include 'text' field for identifiers/literals, but not for source files.
|
||||
if (n.kind !== ts.SyntaxKind.SourceFile) {
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
return JSON.stringify(file, (k, v) => {
|
||||
return Test262BaselineRunner.isNodeOrArray(v) ? serializeNode(v) : v;
|
||||
}, " ");
|
||||
}
|
||||
|
||||
private static isNodeOrArray(a: any): boolean {
|
||||
return a !== undefined && typeof a.pos === "number";
|
||||
}
|
||||
|
||||
private runTest(filePath: string) {
|
||||
describe('test262 test for ' + filePath, () => {
|
||||
// Mocha holds onto the closure environment of the describe callback even after the test is done.
|
||||
|
@ -196,7 +85,7 @@ class Test262BaselineRunner extends RunnerBase {
|
|||
it('has the expected AST',() => {
|
||||
Harness.Baseline.runBaseline('has the expected AST', testState.filename + '.AST.txt',() => {
|
||||
var sourceFile = testState.checker.getProgram().getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename));
|
||||
return Test262BaselineRunner.serializeSourceFile(sourceFile);
|
||||
return Utils.sourceFileToJSON(sourceFile);
|
||||
}, false, Test262BaselineRunner.baselineOptions);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue