Skip to content

Commit 59206d4

Browse files
committed
start on hat stats and golden tests
1 parent f17bdf2 commit 59206d4

17 files changed

+1868
-2
lines changed

Diff for: packages/common/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,4 @@ export * from "./getFakeCommandServerApi";
8686
export * from "./types/TestCaseFixture";
8787
export * from "./util/getEnvironmentVariableStrict";
8888
export * from "./util/CompositeKeyDefaultMap";
89+
export { MockTextDocument, MockTextEditor } from "./testUtil/mockEditor";

Diff for: packages/common/src/testUtil/mockEditor.test.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as assert from "assert";
2+
import { MockTextDocument, Range } from "..";
3+
4+
suite("mockEditor", () => {
5+
test("basic", () => {
6+
const s = "abc\n\n123\n";
7+
const doc: MockTextDocument = new MockTextDocument(
8+
"test.txt",
9+
"plaintext",
10+
s,
11+
);
12+
13+
for (let i = 0; i < s.length; i++) {
14+
const pos = doc.positionAt(i);
15+
const offset = doc.offsetAt(pos);
16+
assert.equal(offset, i);
17+
}
18+
const line0 = doc.lineAt(0);
19+
assert.equal(line0.text, "abc");
20+
assert.equal(line0.firstNonWhitespaceCharacterIndex, 0);
21+
assert.equal(line0.isEmptyOrWhitespace, false);
22+
assert.equal(line0.lineNumber, 0);
23+
assert.ok(line0.range.isEqual(new Range(0, 0, 0, 3)));
24+
assert.equal(line0.rangeIncludingLineBreak.start.character, 0);
25+
assert.equal(line0.lastNonWhitespaceCharacterIndex, 2);
26+
27+
const line1 = doc.lineAt(1);
28+
assert.equal(line1.text, "");
29+
assert.equal(line1.firstNonWhitespaceCharacterIndex, 0);
30+
assert.equal(line1.isEmptyOrWhitespace, true);
31+
assert.equal(line1.lineNumber, 1);
32+
assert.ok(line1.range.isEqual(new Range(1, 0, 1, 0)));
33+
assert.equal(line1.rangeIncludingLineBreak.start.character, 0);
34+
assert.equal(line1.lastNonWhitespaceCharacterIndex, 0);
35+
});
36+
});

Diff for: packages/common/src/testUtil/mockEditor.ts

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import { URI } from "vscode-uri";
2+
import {
3+
EndOfLine,
4+
Position,
5+
Range,
6+
Selection,
7+
TextDocument,
8+
TextEditor,
9+
TextEditorOptions,
10+
TextLine,
11+
} from "..";
12+
13+
// See the TextLine, TextEditor, and TextDocument interfaces
14+
// for documentation of these classes and their fields.
15+
16+
export class MockTextLine implements TextLine {
17+
readonly lineNumber: number;
18+
readonly text: string;
19+
private eol: string;
20+
readonly range: Range;
21+
readonly rangeIncludingLineBreak: Range;
22+
readonly firstNonWhitespaceCharacterIndex: number;
23+
readonly lastNonWhitespaceCharacterIndex: number;
24+
readonly isEmptyOrWhitespace: boolean;
25+
26+
constructor(lineNumber: number, text: string, eol: string) {
27+
if (lineNumber < 0) {
28+
throw new Error("lineNumber must be non-negative");
29+
}
30+
this.lineNumber = lineNumber;
31+
this.text = text;
32+
if (eol !== "\n" && eol !== "\r\n") {
33+
throw new Error("eol must be \\n or \\r\\n");
34+
}
35+
this.eol = eol;
36+
this.range = new Range(
37+
this.lineNumber,
38+
0,
39+
this.lineNumber,
40+
this.text.length,
41+
);
42+
this.rangeIncludingLineBreak = new Range(
43+
this.lineNumber,
44+
0,
45+
this.lineNumber,
46+
this.text.length + this.eol.length,
47+
);
48+
const first = this.text.search(/\S/);
49+
this.firstNonWhitespaceCharacterIndex =
50+
first === -1 ? this.text.length : first;
51+
const all = this.text.match(/\S/g);
52+
this.lastNonWhitespaceCharacterIndex = all
53+
? this.text.lastIndexOf(all[all.length - 1])
54+
: 0;
55+
this.isEmptyOrWhitespace =
56+
this.firstNonWhitespaceCharacterIndex === this.text.length;
57+
}
58+
}
59+
60+
export class MockTextDocument implements TextDocument {
61+
readonly uri: URI;
62+
readonly languageId: string;
63+
readonly version: number;
64+
readonly range: Range;
65+
readonly eol: EndOfLine;
66+
private lines: MockTextLine[];
67+
private contents: string;
68+
69+
constructor(filename: string, languageId: string, contents: string) {
70+
this.uri = URI.file(filename);
71+
this.languageId = languageId;
72+
this.version = 1;
73+
if (contents.indexOf("\r\n") !== -1) {
74+
throw new Error("InMemoryTextDocument does not support CRLF (yet?)");
75+
}
76+
this.contents = contents;
77+
const rawLines = contents.split("\n");
78+
this.lines = rawLines.map((line, i) => {
79+
return new MockTextLine(i, line, "\n");
80+
});
81+
this.range = new Range(
82+
0,
83+
0,
84+
this.lineCount - 1,
85+
this.lineLength(this.lineCount - 1),
86+
);
87+
this.eol = "LF";
88+
}
89+
90+
get lineCount(): number {
91+
return this.lines.length;
92+
}
93+
94+
private lineLength(line: number): number {
95+
return this.lines[line].text.length + 1; // EOF
96+
}
97+
98+
public lineAt(x: number | Position): TextLine {
99+
if (typeof x === "number") {
100+
return this.lines[x];
101+
}
102+
return this.lines[x.line];
103+
}
104+
105+
public offsetAt(position: Position): number {
106+
let offset = 0;
107+
for (let i = 0; i < position.line; i++) {
108+
offset += this.lineAt(i).rangeIncludingLineBreak.end.character;
109+
}
110+
offset += position.character;
111+
return offset;
112+
}
113+
114+
public positionAt(offset: number): Position {
115+
let line = 0;
116+
while (offset >= this.lineAt(line).rangeIncludingLineBreak.end.character) {
117+
offset -= this.lineAt(line).rangeIncludingLineBreak.end.character;
118+
line++;
119+
}
120+
return new Position(line, offset);
121+
}
122+
123+
public getText(range?: Range): string {
124+
if (range === undefined) {
125+
return this.contents;
126+
}
127+
const startOffset = this.offsetAt(range.start);
128+
const endOffset = this.offsetAt(range.end);
129+
return this.contents.slice(startOffset, endOffset);
130+
}
131+
}
132+
133+
export class MockTextEditor implements TextEditor {
134+
public primarySelection: Selection;
135+
readonly id: string;
136+
readonly document: TextDocument;
137+
readonly options: TextEditorOptions;
138+
readonly isActive: boolean;
139+
140+
constructor(document: TextDocument, active: boolean) {
141+
this.id = document.uri.toString();
142+
this.document = document;
143+
this.primarySelection = new Selection(0, 0, 0, 0);
144+
this.options = new DefaultTextEditorOptions();
145+
this.isActive = active;
146+
// TODO: support visible ranges, multiple selections, options
147+
}
148+
149+
get visibleRanges(): Range[] {
150+
return [this.document.range];
151+
}
152+
153+
get selections(): Selection[] {
154+
return [this.primarySelection];
155+
}
156+
157+
isEqual(other: TextEditor): boolean {
158+
return this.id === other.id;
159+
}
160+
}
161+
162+
class DefaultTextEditorOptions implements TextEditorOptions {
163+
get tabSize(): number | string {
164+
return 4;
165+
}
166+
167+
get insertSpaces(): boolean | string {
168+
return true;
169+
}
170+
}

Diff for: packages/common/src/types/Position.ts

+8
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,12 @@ export class Position {
138138
public toEmptyRange(): Range {
139139
return new Range(this, this);
140140
}
141+
142+
/**
143+
* Return a concise string representation of the position, for debugging
144+
* @returns concise representation
145+
**/
146+
public concise(): string {
147+
return `${this.line}:${this.character}`;
148+
}
141149
}

Diff for: packages/common/src/types/Range.ts

+19
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ export class Range {
6464
return this.start.isEqual(this.end);
6565
}
6666

67+
/**
68+
* Check if this range is equal to `other`.
69+
*
70+
* @param other A range.
71+
* @return `true` if the start and end of the given range are equal to
72+
* the start and end of this range.
73+
*/
74+
public isEqual(other: Range): boolean {
75+
return this.start.isEqual(other.start) && this.end.isEqual(other.end);
76+
}
77+
6778
/**
6879
* `true` if `start.line` and `end.line` are equal.
6980
*/
@@ -146,4 +157,12 @@ export class Range {
146157
? new Selection(this.end, this.start)
147158
: new Selection(this.start, this.end);
148159
}
160+
161+
/**
162+
* Return a concise string representation of the range, for debugging
163+
* @returns concise representation
164+
**/
165+
public concise(): string {
166+
return `${this.start.concise()}-${this.end.concise()}`;
167+
}
149168
}

0 commit comments

Comments
 (0)