diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1352f5c71c5..ffe23c9d36d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -534,7 +534,7 @@ module ts { return true; } else { - if (child.pos > position && position < child.end) { + if (child.pos < position && position < child.end) { // Position in somewhere within this child. Search in it and // stop searching in this array. forEachChild(child, visitNode, visitArray); @@ -1616,7 +1616,7 @@ module ts { while (!isListTerminator(kind)) { if (isListElement(kind, /* inErrorRecovery */ false)) { - var element = currentNode(kind) || parseElement(); + var element = parseListElement(kind, parseElement); result.push(element); // test elements only if we are not already in strict mode @@ -1646,6 +1646,15 @@ module ts { return result; } + function parseListElement(kind: ParsingContext, parseElement: () => T): T { + var node = currentNode(kind); + if (node) { + return consumeNode(node); + } + + return parseElement(); + } + function currentNode(parsingContext: ParsingContext): Node { // If there is an outstanding parse error that we've encountered, but not attached to // some node, then we cannot get a node from the old source tree. This is because we @@ -1663,7 +1672,7 @@ module ts { return undefined; } - var node = syntaxCursor.currentNode(scanner.getTextPos()); + var node = syntaxCursor.currentNode(scanner.getStartPos()); // Can't reuse a missing node. if (isMissingNode(node)) { @@ -1686,7 +1695,8 @@ module ts { // differently depending on what mode it is in. // // This also applies to all our other context flags as well. - if (node.parserContextFlags !== contextFlags) { + var nodeContextFlags = node.parserContextFlags || 0; + if (nodeContextFlags !== contextFlags) { return undefined; } @@ -1696,13 +1706,11 @@ module ts { return undefined; } - // It was valid. Let teh source know we're consuming this node, and pass to the list - // parser. - return consumeNode(node); + return node; } function consumeNode(node: Node) { - // Move the scanner so it is after the node we just consumed + // Move the scanner so it is after the node we just consumed. scanner.setTextPos(node.end); nextToken(); return node; @@ -1944,7 +1952,7 @@ module ts { var commaStart = -1; // Meaning the previous token was not a comma while (true) { if (isListElement(kind, /* inErrorRecovery */ false)) { - result.push(currentNode(kind) || parseElement()); + result.push(parseListElement(kind, parseElement)); commaStart = scanner.getTokenPos(); if (parseOptional(SyntaxKind.CommaToken)) { continue; diff --git a/tests/cases/unittests/incrementalParser.ts b/tests/cases/unittests/incrementalParser.ts index fd4d31197d7..8a57556363d 100644 --- a/tests/cases/unittests/incrementalParser.ts +++ b/tests/cases/unittests/incrementalParser.ts @@ -192,7 +192,7 @@ module ts { var semicolonIndex = source.indexOf(";"); var newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); }); it('Deleting from method',() => { @@ -208,7 +208,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withDelete(oldText, index, "+ 1".length); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); }); it('Regular expression 1',() => { @@ -228,7 +228,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, semicolonIndex, "/"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); it('Comment 1',() => { @@ -266,7 +266,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, index, "*"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); it('Parameter 1',() => { @@ -281,7 +281,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, semicolonIndex, " + 1"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 8); }); it('Type member 1',() => { @@ -292,7 +292,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, index, "?"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 14); }); it('Enum element 1',() => { @@ -303,7 +303,7 @@ module ts { var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withChange(oldText, index, 2, "+"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 21); }); it('Strict mode 1',() => { @@ -600,7 +600,7 @@ module ts { var index = source.lastIndexOf(";"); var newTextAndChange = withDelete(oldText, index, 1); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 4); }); it('Edit after empty type parameter list',() => { @@ -634,7 +634,7 @@ var o2 = { set Foo(val:number) { } };"; var index = source.indexOf("set"); var newTextAndChange = withInsert(oldText, index, "public "); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 6); }); it('Insert parameter ahead of parameter',() => { @@ -650,7 +650,7 @@ constructor(name) { }\ var index = source.indexOf("100"); var newTextAndChange = withInsert(oldText, index, "'1', "); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 5); }); it('Insert declare modifier before module',() => { @@ -663,7 +663,7 @@ module m3 { }\ var index = 0; var newTextAndChange = withInsert(oldText, index, "declare "); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 3); }); it('Insert function above arrow function with comment',() => { @@ -719,7 +719,7 @@ module m3 { }\ var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withInsert(oldText, 0, ""); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 7); }); it('Class to interface',() => { @@ -782,7 +782,7 @@ module m3 { }\ var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withChange(oldText, 0, "class".length, "interface"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); }); it('Moving index signatures from interface to class',() => { @@ -791,7 +791,7 @@ module m3 { }\ var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withChange(oldText, 0, "interface".length, "class"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 18); }); it('Moving accessors from class to object literal',() => { @@ -809,7 +809,7 @@ module m3 { }\ var oldText = ScriptSnapshot.fromString(source); var newTextAndChange = withChange(oldText, 0, "var v =".length, "class C"); - compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 0); + compareTrees(oldText, newTextAndChange.text, newTextAndChange.textChangeRange, 16); }); // Simulated typing tests.