Skip to content

Commit 888b88e

Browse files
Move textSpan and textChangeRange impls to the compiler layer.
1 parent c2d4cd5 commit 888b88e

6 files changed

Lines changed: 224 additions & 308 deletions

File tree

src/compiler/types.ts

Lines changed: 218 additions & 140 deletions
Large diffs are not rendered by default.

src/harness/harnessLanguageService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module Harness.LanguageService {
3232
// Store edit range + new length of script
3333
this.editRanges.push({
3434
length: this.content.length,
35-
textChangeRange: new ts.TextChangeRangeObject(
35+
textChangeRange: ts.createTextChangeRange(
3636
ts.createTextSpanFromBounds(minChar, limChar), newText.length)
3737
});
3838

@@ -43,14 +43,14 @@ module Harness.LanguageService {
4343
public getTextChangeRangeBetweenVersions(startVersion: number, endVersion: number): ts.TextChangeRange {
4444
if (startVersion === endVersion) {
4545
// No edits!
46-
return ts.TextChangeRangeObject.unchanged;
46+
return ts.unchangedTextChangeRange;
4747
}
4848

4949
var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion);
5050
var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion);
5151

5252
var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex);
53-
return ts.TextChangeRangeObject.collapseChangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
53+
return ts.collapseTextChangeRangesAcrossMultipleVersions(entries.map(e => e.textChangeRange));
5454
}
5555
}
5656

src/services/services.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1613,7 +1613,7 @@ module ts {
16131613
public getChangeRange(filename: string, lastKnownVersion: string, oldScriptSnapshot: IScriptSnapshot): TextChangeRange {
16141614
var currentVersion = this.getVersion(filename);
16151615
if (lastKnownVersion === currentVersion) {
1616-
return TextChangeRangeObject.unchanged; // "No changes"
1616+
return unchangedTextChangeRange; // "No changes"
16171617
}
16181618

16191619
var scriptSnapshot = this.getScriptSnapshot(filename);

src/services/shims.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ module ts {
328328
}
329329

330330
var decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded);
331-
return new TextChangeRangeObject(
331+
return createTextChangeRange(
332332
createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
333333
}
334334
}

src/services/text.ts

Lines changed: 0 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -1,164 +1,2 @@
11
module ts {
2-
export class TextChangeRangeObject implements TextChangeRange {
3-
public static unchanged = new TextChangeRangeObject(createTextSpan(0, 0), 0);
4-
5-
private _span: TextSpan;
6-
private _newLength: number;
7-
8-
/**
9-
* Initializes a new instance of TextChangeRange.
10-
*/
11-
constructor(span: TextSpan, newLength: number) {
12-
Debug.assert(newLength >= 0, "newLength");
13-
14-
this._span = span;
15-
this._newLength = newLength;
16-
}
17-
18-
/**
19-
* The span of text before the edit which is being changed
20-
*/
21-
public span(): TextSpan {
22-
return this._span;
23-
}
24-
25-
/**
26-
* Width of the span after the edit. A 0 here would represent a delete
27-
*/
28-
public newLength(): number {
29-
return this._newLength;
30-
}
31-
32-
public newSpan(): TextSpan {
33-
return createTextSpan(this.span().start(), this.newLength());
34-
}
35-
36-
public isUnchanged(): boolean {
37-
return this.span().isEmpty() && this.newLength() === 0;
38-
}
39-
40-
/**
41-
* Called to merge all the changes that occurred across several versions of a script snapshot
42-
* into a single change. i.e. if a user keeps making successive edits to a script we will
43-
* have a text change from V1 to V2, V2 to V3, ..., Vn.
44-
*
45-
* This function will then merge those changes into a single change range valid between V1 and
46-
* Vn.
47-
*/
48-
public static collapseChangesAcrossMultipleVersions(changes: TextChangeRange[]): TextChangeRange {
49-
if (changes.length === 0) {
50-
return TextChangeRangeObject.unchanged;
51-
}
52-
53-
if (changes.length === 1) {
54-
return changes[0];
55-
}
56-
57-
// We change from talking about { { oldStart, oldLength }, newLength } to { oldStart, oldEnd, newEnd }
58-
// as it makes things much easier to reason about.
59-
var change0 = changes[0];
60-
61-
var oldStartN = change0.span().start();
62-
var oldEndN = change0.span().end();
63-
var newEndN = oldStartN + change0.newLength();
64-
65-
for (var i = 1; i < changes.length; i++) {
66-
var nextChange = changes[i];
67-
68-
// Consider the following case:
69-
// i.e. two edits. The first represents the text change range { { 10, 50 }, 30 }. i.e. The span starting
70-
// at 10, with length 50 is reduced to length 30. The second represents the text change range { { 30, 30 }, 40 }.
71-
// i.e. the span starting at 30 with length 30 is increased to length 40.
72-
//
73-
// 0 10 20 30 40 50 60 70 80 90 100
74-
// -------------------------------------------------------------------------------------------------------
75-
// | /
76-
// | /----
77-
// T1 | /----
78-
// | /----
79-
// | /----
80-
// -------------------------------------------------------------------------------------------------------
81-
// | \
82-
// | \
83-
// T2 | \
84-
// | \
85-
// | \
86-
// -------------------------------------------------------------------------------------------------------
87-
//
88-
// Merging these turns out to not be too difficult. First, determining the new start of the change is trivial
89-
// it's just the min of the old and new starts. i.e.:
90-
//
91-
// 0 10 20 30 40 50 60 70 80 90 100
92-
// ------------------------------------------------------------*------------------------------------------
93-
// | /
94-
// | /----
95-
// T1 | /----
96-
// | /----
97-
// | /----
98-
// ----------------------------------------$-------------------$------------------------------------------
99-
// . | \
100-
// . | \
101-
// T2 . | \
102-
// . | \
103-
// . | \
104-
// ----------------------------------------------------------------------*--------------------------------
105-
//
106-
// (Note the dots represent the newly inferrred start.
107-
// Determining the new and old end is also pretty simple. Basically it boils down to paying attention to the
108-
// absolute positions at the asterixes, and the relative change between the dollar signs. Basically, we see
109-
// which if the two $'s precedes the other, and we move that one forward until they line up. in this case that
110-
// means:
111-
//
112-
// 0 10 20 30 40 50 60 70 80 90 100
113-
// --------------------------------------------------------------------------------*----------------------
114-
// | /
115-
// | /----
116-
// T1 | /----
117-
// | /----
118-
// | /----
119-
// ------------------------------------------------------------$------------------------------------------
120-
// . | \
121-
// . | \
122-
// T2 . | \
123-
// . | \
124-
// . | \
125-
// ----------------------------------------------------------------------*--------------------------------
126-
//
127-
// In other words (in this case), we're recognizing that the second edit happened after where the first edit
128-
// ended with a delta of 20 characters (60 - 40). Thus, if we go back in time to where the first edit started
129-
// that's the same as if we started at char 80 instead of 60.
130-
//
131-
// As it so happens, the same logic applies if the second edit precedes the first edit. In that case rahter
132-
// than pusing the first edit forward to match the second, we'll push the second edit forward to match the
133-
// first.
134-
//
135-
// In this case that means we have { oldStart: 10, oldEnd: 80, newEnd: 70 } or, in TextChangeRange
136-
// semantics: { { start: 10, length: 70 }, newLength: 60 }
137-
//
138-
// The math then works out as follows.
139-
// If we have { oldStart1, oldEnd1, newEnd1 } and { oldStart2, oldEnd2, newEnd2 } then we can compute the
140-
// final result like so:
141-
//
142-
// {
143-
// oldStart3: Min(oldStart1, oldStart2),
144-
// oldEnd3 : Max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1)),
145-
// newEnd3 : Max(newEnd2, newEnd2 + (newEnd1 - oldEnd2))
146-
// }
147-
148-
var oldStart1 = oldStartN;
149-
var oldEnd1 = oldEndN;
150-
var newEnd1 = newEndN;
151-
152-
var oldStart2 = nextChange.span().start();
153-
var oldEnd2 = nextChange.span().end();
154-
var newEnd2 = oldStart2 + nextChange.newLength();
155-
156-
oldStartN = Math.min(oldStart1, oldStart2);
157-
oldEndN = Math.max(oldEnd1, oldEnd1 + (oldEnd2 - newEnd1));
158-
newEndN = Math.max(newEnd2, newEnd2 + (newEnd1 - oldEnd2));
159-
}
160-
161-
return new TextChangeRangeObject(createTextSpanFromBounds(oldStartN, oldEndN), /*newLength: */newEndN - oldStartN);
162-
}
163-
}
1642
}

tests/cases/unittests/incrementalParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module ts {
66
var contents = text.getText(0, text.getLength());
77
var newContents = contents.substr(0, start) + newText + contents.substring(start + length);
88

9-
return { text: ScriptSnapshot.fromString(newContents), textChangeRange: new TextChangeRangeObject(createTextSpan(start, length), newText.length) }
9+
return { text: ScriptSnapshot.fromString(newContents), textChangeRange: createTextChangeRange(createTextSpan(start, length), newText.length) }
1010
}
1111

1212
function withInsert(text: IScriptSnapshot, start: number, newText: string): { text: IScriptSnapshot; textChangeRange: TextChangeRange; } {

0 commit comments

Comments
 (0)