Merge pull request #620 from Microsoft/incrementalParsingBug
Fix incremental parsing bug due to non invalidating cached data in nodes...
This commit is contained in:
commit
1eacacdc24
|
@ -1084,6 +1084,8 @@ module FourSlash {
|
||||||
// Make the edit
|
// Make the edit
|
||||||
var ch = text.charAt(i);
|
var ch = text.charAt(i);
|
||||||
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset, ch);
|
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset, ch);
|
||||||
|
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
|
||||||
|
|
||||||
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
|
||||||
this.editCheckpoint(this.activeFile.fileName);
|
this.editCheckpoint(this.activeFile.fileName);
|
||||||
offset++;
|
offset++;
|
||||||
|
|
|
@ -544,19 +544,30 @@ module TypeScript.Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceTokenInParent(oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
|
function replaceTokenInParent(node: ISyntaxNode, oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
|
||||||
// oldToken may be parented by a node or a list.
|
// oldToken may be parented by a node or a list.
|
||||||
replaceTokenInParentWorker(oldToken, newToken);
|
replaceTokenInParentWorker(oldToken, newToken);
|
||||||
|
|
||||||
var parent = oldToken.parent;
|
var parent = oldToken.parent;
|
||||||
newToken.parent = parent;
|
newToken.parent = parent;
|
||||||
|
|
||||||
|
// Walk upwards to our outermost node, clearing hte cached 'data' in it. This will
|
||||||
|
// make sure that the fullWidths and incrementally unusable bits are computed correctly
|
||||||
|
// when next requested.
|
||||||
|
while (true) {
|
||||||
// Parent must be a list or a node. All of those have a 'data' element.
|
// Parent must be a list or a node. All of those have a 'data' element.
|
||||||
Debug.assert(isNode(parent) || isList(parent) || isSeparatedList(parent));
|
Debug.assert(isNode(parent) || isList(parent) || isSeparatedList(parent));
|
||||||
var dataElement = <{ data: number }><any>parent;
|
var dataElement = <{ data: number }><any>parent;
|
||||||
if (dataElement.data) {
|
if (dataElement.data) {
|
||||||
dataElement.data &= SyntaxConstants.NodeParsedInStrictModeMask
|
dataElement.data &= SyntaxConstants.NodeParsedInStrictModeMask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent === node) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceTokenInParentWorker(oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
|
function replaceTokenInParentWorker(oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
|
||||||
|
@ -602,7 +613,7 @@ module TypeScript.Parser {
|
||||||
var oldToken = lastToken(node);
|
var oldToken = lastToken(node);
|
||||||
var newToken = addSkippedTokenAfterToken(oldToken, skippedToken);
|
var newToken = addSkippedTokenAfterToken(oldToken, skippedToken);
|
||||||
|
|
||||||
replaceTokenInParent(oldToken, newToken);
|
replaceTokenInParent(node, oldToken, newToken);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,7 +622,7 @@ module TypeScript.Parser {
|
||||||
var oldToken = firstToken(node);
|
var oldToken = firstToken(node);
|
||||||
var newToken = addSkippedTokensBeforeToken(oldToken, skippedTokens);
|
var newToken = addSkippedTokensBeforeToken(oldToken, skippedTokens);
|
||||||
|
|
||||||
replaceTokenInParent(oldToken, newToken);
|
replaceTokenInParent(node, oldToken, newToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
26
tests/cases/fourslash/incrementalParsing1.ts
Normal file
26
tests/cases/fourslash/incrementalParsing1.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/// <reference path="fourslash.ts"/>
|
||||||
|
|
||||||
|
//// function foo() {
|
||||||
|
//// function getOccurrencesAtPosition() {
|
||||||
|
//// switch (node) {
|
||||||
|
//// enum /*1*/
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// return undefined;
|
||||||
|
////
|
||||||
|
//// function keywordToReferenceEntry() {
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// return {
|
||||||
|
//// getEmitOutput: (filename): Bar => null,
|
||||||
|
//// };
|
||||||
|
//// }
|
||||||
|
|
||||||
|
// Force a syntax tree ot be created.
|
||||||
|
verify.noMatchingBracePositionInCurrentFile(0);
|
||||||
|
|
||||||
|
// make sure we check the tree after every edit.
|
||||||
|
diagnostics.setTypingFidelity(TypingFidelity.High);
|
||||||
|
goTo.marker('1');
|
||||||
|
edit.insert('Fo');
|
Loading…
Reference in a new issue