Merge pull request #1992 from Microsoft/additionalParserChecks
Additional parser checks
This commit is contained in:
commit
b277695a54
1 changed files with 40 additions and 46 deletions
|
@ -371,8 +371,8 @@ module ts {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveElementEntirelyPastChangeRange(element: IncrementalElement, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
|
function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
|
||||||
if (element.length) {
|
if (isArray) {
|
||||||
visitArray(<IncrementalNodeArray>element);
|
visitArray(<IncrementalNodeArray>element);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -400,6 +400,7 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function visitArray(array: IncrementalNodeArray) {
|
function visitArray(array: IncrementalNodeArray) {
|
||||||
|
array._children = undefined;
|
||||||
array.pos += delta;
|
array.pos += delta;
|
||||||
array.end += delta;
|
array.end += delta;
|
||||||
|
|
||||||
|
@ -412,6 +413,7 @@ module ts {
|
||||||
function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
|
function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
|
||||||
Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
|
Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
|
||||||
Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
|
Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
|
||||||
|
Debug.assert(element.pos <= element.end);
|
||||||
|
|
||||||
// We have an element that intersects the change range in some way. It may have its
|
// We have an element that intersects the change range in some way. It may have its
|
||||||
// start, or its end (or both) in the changed range. We want to adjust any part
|
// start, or its end (or both) in the changed range. We want to adjust any part
|
||||||
|
@ -508,10 +510,11 @@ module ts {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
function visitNode(child: IncrementalNode) {
|
function visitNode(child: IncrementalNode) {
|
||||||
|
Debug.assert(child.pos <= child.end);
|
||||||
if (child.pos > changeRangeOldEnd) {
|
if (child.pos > changeRangeOldEnd) {
|
||||||
// Node is entirely past the change range. We need to move both its pos and
|
// Node is entirely past the change range. We need to move both its pos and
|
||||||
// end, forward or backward appropriately.
|
// end, forward or backward appropriately.
|
||||||
moveElementEntirelyPastChangeRange(child, delta, oldText, newText, aggressiveChecks);
|
moveElementEntirelyPastChangeRange(child, /*isArray:*/ false, delta, oldText, newText, aggressiveChecks);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,6 +524,7 @@ module ts {
|
||||||
var fullEnd = child.end;
|
var fullEnd = child.end;
|
||||||
if (fullEnd >= changeStart) {
|
if (fullEnd >= changeStart) {
|
||||||
child.intersectsChange = true;
|
child.intersectsChange = true;
|
||||||
|
child._children = undefined;
|
||||||
|
|
||||||
// Adjust the pos or end (or both) of the intersecting element accordingly.
|
// Adjust the pos or end (or both) of the intersecting element accordingly.
|
||||||
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
|
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
|
||||||
|
@ -531,32 +535,36 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, the node is entirely before the change range. No need to do anything with it.
|
// Otherwise, the node is entirely before the change range. No need to do anything with it.
|
||||||
|
Debug.assert(fullEnd < changeStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
function visitArray(array: IncrementalNodeArray) {
|
function visitArray(array: IncrementalNodeArray) {
|
||||||
|
Debug.assert(array.pos <= array.end);
|
||||||
if (array.pos > changeRangeOldEnd) {
|
if (array.pos > changeRangeOldEnd) {
|
||||||
// Array is entirely after the change range. We need to move it, and move any of
|
// Array is entirely after the change range. We need to move it, and move any of
|
||||||
// its children.
|
// its children.
|
||||||
moveElementEntirelyPastChangeRange(array, delta, oldText, newText, aggressiveChecks);
|
moveElementEntirelyPastChangeRange(array, /*isArray:*/ true, delta, oldText, newText, aggressiveChecks);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
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 = array.end;
|
|
||||||
if (fullEnd >= changeStart) {
|
|
||||||
array.intersectsChange = true;
|
|
||||||
|
|
||||||
// Adjust the pos or end (or both) of the intersecting array accordingly.
|
// Check if the element intersects the change range. If it does, then it is not
|
||||||
adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
|
// reusable. Also, we'll need to recurse to see what constituent portions we may
|
||||||
for (var i = 0, n = array.length; i < n; i++) {
|
// be able to use.
|
||||||
visitNode(array[i]);
|
var fullEnd = array.end;
|
||||||
}
|
if (fullEnd >= changeStart) {
|
||||||
|
array.intersectsChange = true;
|
||||||
|
array._children = undefined;
|
||||||
|
|
||||||
|
// Adjust the pos or end (or both) of the intersecting array accordingly.
|
||||||
|
adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
|
||||||
|
for (var i = 0, n = array.length; i < n; i++) {
|
||||||
|
visitNode(array[i]);
|
||||||
}
|
}
|
||||||
// else {
|
return;
|
||||||
// Otherwise, the array is entirely before the change range. No need to do anything with it.
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, the array is entirely before the change range. No need to do anything with it.
|
||||||
|
Debug.assert(fullEnd < changeStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +850,7 @@ module ts {
|
||||||
// Much of the time the parser will need the very next node in the array that
|
// Much of the time the parser will need the very next node in the array that
|
||||||
// we just returned a node from.So just simply check for that case and move
|
// we just returned a node from.So just simply check for that case and move
|
||||||
// forward in the array instead of searching for the node again.
|
// forward in the array instead of searching for the node again.
|
||||||
if (current && current.end === position && currentArrayIndex < currentArray.length) {
|
if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
|
||||||
currentArrayIndex++;
|
currentArrayIndex++;
|
||||||
current = currentArray[currentArrayIndex];
|
current = currentArray[currentArrayIndex];
|
||||||
}
|
}
|
||||||
|
@ -878,6 +886,7 @@ module ts {
|
||||||
|
|
||||||
// Recurse into the source file to find the highest node at this position.
|
// Recurse into the source file to find the highest node at this position.
|
||||||
forEachChild(sourceFile, visitNode, visitArray);
|
forEachChild(sourceFile, visitNode, visitArray);
|
||||||
|
return;
|
||||||
|
|
||||||
function visitNode(node: Node) {
|
function visitNode(node: Node) {
|
||||||
if (position >= node.pos && position < node.end) {
|
if (position >= node.pos && position < node.end) {
|
||||||
|
@ -1649,8 +1658,8 @@ module ts {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseListElement<T extends Node>(kind: ParsingContext, parseElement: () => T): T {
|
function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
|
||||||
var node = currentNode(kind);
|
var node = currentNode(parsingContext);
|
||||||
if (node) {
|
if (node) {
|
||||||
return <T>consumeNode(node);
|
return <T>consumeNode(node);
|
||||||
}
|
}
|
||||||
|
@ -1807,29 +1816,10 @@ module ts {
|
||||||
case SyntaxKind.InterfaceDeclaration:
|
case SyntaxKind.InterfaceDeclaration:
|
||||||
case SyntaxKind.ModuleDeclaration:
|
case SyntaxKind.ModuleDeclaration:
|
||||||
case SyntaxKind.EnumDeclaration:
|
case SyntaxKind.EnumDeclaration:
|
||||||
|
|
||||||
// Keep in sync with isStatement:
|
|
||||||
case SyntaxKind.FunctionDeclaration:
|
|
||||||
case SyntaxKind.VariableStatement:
|
|
||||||
case SyntaxKind.Block:
|
|
||||||
case SyntaxKind.IfStatement:
|
|
||||||
case SyntaxKind.ExpressionStatement:
|
|
||||||
case SyntaxKind.ThrowStatement:
|
|
||||||
case SyntaxKind.ReturnStatement:
|
|
||||||
case SyntaxKind.SwitchStatement:
|
|
||||||
case SyntaxKind.BreakStatement:
|
|
||||||
case SyntaxKind.ContinueStatement:
|
|
||||||
case SyntaxKind.ForInStatement:
|
|
||||||
case SyntaxKind.ForStatement:
|
|
||||||
case SyntaxKind.WhileStatement:
|
|
||||||
case SyntaxKind.WithStatement:
|
|
||||||
case SyntaxKind.EmptyStatement:
|
|
||||||
case SyntaxKind.TryStatement:
|
|
||||||
case SyntaxKind.LabeledStatement:
|
|
||||||
case SyntaxKind.DoStatement:
|
|
||||||
case SyntaxKind.DebuggerStatement:
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isReusableStatement(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1935,9 +1925,13 @@ module ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isReusableParameter(node: Node) {
|
function isReusableParameter(node: Node) {
|
||||||
// TODO: this most likely needs the same initializer check that
|
if (node.kind !== SyntaxKind.Parameter) {
|
||||||
// isReusableVariableDeclaration has.
|
return false;
|
||||||
return node.kind === SyntaxKind.Parameter;
|
}
|
||||||
|
|
||||||
|
// See the comment in isReusableVariableDeclaration for why we do this.
|
||||||
|
var parameter = <ParameterDeclaration>node;
|
||||||
|
return parameter.initializer === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if we should abort parsing.
|
// Returns true if we should abort parsing.
|
||||||
|
|
Loading…
Reference in a new issue