Skip to content

Commit 1eacacd

Browse files
Merge pull request #620 from Microsoft/incrementalParsingBug
Fix incremental parsing bug due to non invalidating cached data in nodes...
2 parents 90ecf81 + aeb428e commit 1eacacd

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

src/harness/fourslash.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,8 @@ module FourSlash {
10841084
// Make the edit
10851085
var ch = text.charAt(i);
10861086
this.languageServiceShimHost.editScript(this.activeFile.fileName, offset, offset, ch);
1087+
this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset);
1088+
10871089
this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, ch);
10881090
this.editCheckpoint(this.activeFile.fileName);
10891091
offset++;

src/services/syntax/parser.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -544,18 +544,29 @@ module TypeScript.Parser {
544544
}
545545
}
546546

547-
function replaceTokenInParent(oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
547+
function replaceTokenInParent(node: ISyntaxNode, oldToken: ISyntaxToken, newToken: ISyntaxToken): void {
548548
// oldToken may be parented by a node or a list.
549549
replaceTokenInParentWorker(oldToken, newToken);
550550

551551
var parent = oldToken.parent;
552552
newToken.parent = parent;
553553

554-
// Parent must be a list or a node. All of those have a 'data' element.
555-
Debug.assert(isNode(parent) || isList(parent) || isSeparatedList(parent));
556-
var dataElement = <{ data: number }><any>parent;
557-
if (dataElement.data) {
558-
dataElement.data &= SyntaxConstants.NodeParsedInStrictModeMask
554+
// Walk upwards to our outermost node, clearing hte cached 'data' in it. This will
555+
// make sure that the fullWidths and incrementally unusable bits are computed correctly
556+
// when next requested.
557+
while (true) {
558+
// Parent must be a list or a node. All of those have a 'data' element.
559+
Debug.assert(isNode(parent) || isList(parent) || isSeparatedList(parent));
560+
var dataElement = <{ data: number }><any>parent;
561+
if (dataElement.data) {
562+
dataElement.data &= SyntaxConstants.NodeParsedInStrictModeMask
563+
}
564+
565+
if (parent === node) {
566+
break;
567+
}
568+
569+
parent = parent.parent;
559570
}
560571
}
561572

@@ -602,7 +613,7 @@ module TypeScript.Parser {
602613
var oldToken = lastToken(node);
603614
var newToken = addSkippedTokenAfterToken(oldToken, skippedToken);
604615

605-
replaceTokenInParent(oldToken, newToken);
616+
replaceTokenInParent(node, oldToken, newToken);
606617
return node;
607618
}
608619

@@ -611,7 +622,7 @@ module TypeScript.Parser {
611622
var oldToken = firstToken(node);
612623
var newToken = addSkippedTokensBeforeToken(oldToken, skippedTokens);
613624

614-
replaceTokenInParent(oldToken, newToken);
625+
replaceTokenInParent(node, oldToken, newToken);
615626
}
616627

617628
return node;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
//// function foo() {
4+
//// function getOccurrencesAtPosition() {
5+
//// switch (node) {
6+
//// enum /*1*/
7+
//// }
8+
////
9+
//// return undefined;
10+
////
11+
//// function keywordToReferenceEntry() {
12+
//// }
13+
//// }
14+
////
15+
//// return {
16+
//// getEmitOutput: (filename): Bar => null,
17+
//// };
18+
//// }
19+
20+
// Force a syntax tree ot be created.
21+
verify.noMatchingBracePositionInCurrentFile(0);
22+
23+
// make sure we check the tree after every edit.
24+
diagnostics.setTypingFidelity(TypingFidelity.High);
25+
goTo.marker('1');
26+
edit.insert('Fo');

0 commit comments

Comments
 (0)