Skip to content

Commit 66eceaa

Browse files
committed
Fixes some cyclic runtime dependencies
1 parent 5a1a163 commit 66eceaa

File tree

11 files changed

+277
-245
lines changed

11 files changed

+277
-245
lines changed

src/vs/editor/common/core/text/abstractText.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { assert } from '../../../../base/common/assert.js';
77
import { splitLines } from '../../../../base/common/strings.js';
88
import { Position } from '../position.js';
9-
import { PositionOffsetTransformer } from './positionToOffset.js';
9+
import { PositionOffsetTransformer } from './positionToOffsetImpl.js';
1010
import { Range } from '../range.js';
1111
import { LineRange } from '../ranges/lineRange.js';
1212
import { TextLength } from '../text/textLength.js';

src/vs/editor/common/core/text/positionToOffset.ts

Lines changed: 13 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -3,117 +3,17 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { findLastIdxMonotonous } from '../../../../base/common/arraysFind.js';
76
import { StringEdit, StringReplacement } from '../edits/stringEdit.js';
8-
import { OffsetRange } from '../ranges/offsetRange.js';
9-
import { Position } from '../position.js';
10-
import { Range } from '../range.js';
11-
import { TextReplacement, TextEdit } from '../edits/textEdit.js';
12-
import { TextLength } from '../text/textLength.js';
13-
14-
export abstract class PositionOffsetTransformerBase {
15-
abstract getOffset(position: Position): number;
16-
17-
getOffsetRange(range: Range): OffsetRange {
18-
return new OffsetRange(
19-
this.getOffset(range.getStartPosition()),
20-
this.getOffset(range.getEndPosition())
21-
);
22-
}
23-
24-
abstract getPosition(offset: number): Position;
25-
26-
getRange(offsetRange: OffsetRange): Range {
27-
return Range.fromPositions(
28-
this.getPosition(offsetRange.start),
29-
this.getPosition(offsetRange.endExclusive)
30-
);
31-
}
32-
33-
getStringEdit(edit: TextEdit): StringEdit {
34-
const edits = edit.replacements.map(e => this.getStringReplacement(e));
35-
return new StringEdit(edits);
36-
}
37-
38-
getStringReplacement(edit: TextReplacement): StringReplacement {
39-
return new StringReplacement(this.getOffsetRange(edit.range), edit.text);
40-
}
41-
42-
getSingleTextEdit(edit: StringReplacement): TextReplacement {
43-
return new TextReplacement(this.getRange(edit.replaceRange), edit.newText);
44-
}
45-
46-
getTextEdit(edit: StringEdit): TextEdit {
47-
const edits = edit.replacements.map(e => this.getSingleTextEdit(e));
48-
return new TextEdit(edits);
49-
}
50-
}
51-
52-
export class PositionOffsetTransformer extends PositionOffsetTransformerBase {
53-
private readonly lineStartOffsetByLineIdx: number[];
54-
private readonly lineEndOffsetByLineIdx: number[];
55-
56-
constructor(public readonly text: string) {
57-
super();
58-
59-
this.lineStartOffsetByLineIdx = [];
60-
this.lineEndOffsetByLineIdx = [];
61-
62-
this.lineStartOffsetByLineIdx.push(0);
63-
for (let i = 0; i < text.length; i++) {
64-
if (text.charAt(i) === '\n') {
65-
this.lineStartOffsetByLineIdx.push(i + 1);
66-
if (i > 0 && text.charAt(i - 1) === '\r') {
67-
this.lineEndOffsetByLineIdx.push(i - 1);
68-
} else {
69-
this.lineEndOffsetByLineIdx.push(i);
70-
}
71-
}
72-
}
73-
this.lineEndOffsetByLineIdx.push(text.length);
74-
}
75-
76-
override getOffset(position: Position): number {
77-
const valPos = this._validatePosition(position);
78-
return this.lineStartOffsetByLineIdx[valPos.lineNumber - 1] + valPos.column - 1;
79-
}
80-
81-
private _validatePosition(position: Position): Position {
82-
if (position.lineNumber < 1) {
83-
return new Position(1, 1);
84-
}
85-
const lineCount = this.textLength.lineCount + 1;
86-
if (position.lineNumber > lineCount) {
87-
const lineLength = this.getLineLength(lineCount);
88-
return new Position(lineCount, lineLength + 1);
89-
}
90-
if (position.column < 1) {
91-
return new Position(position.lineNumber, 1);
92-
}
93-
const lineLength = this.getLineLength(position.lineNumber);
94-
if (position.column - 1 > lineLength) {
95-
return new Position(position.lineNumber, lineLength + 1);
96-
}
97-
return position;
98-
}
99-
100-
override getPosition(offset: number): Position {
101-
const idx = findLastIdxMonotonous(this.lineStartOffsetByLineIdx, i => i <= offset);
102-
const lineNumber = idx + 1;
103-
const column = offset - this.lineStartOffsetByLineIdx[idx] + 1;
104-
return new Position(lineNumber, column);
105-
}
106-
107-
getTextLength(offsetRange: OffsetRange): TextLength {
108-
return TextLength.ofRange(this.getRange(offsetRange));
109-
}
110-
111-
get textLength(): TextLength {
112-
const lineIdx = this.lineStartOffsetByLineIdx.length - 1;
113-
return new TextLength(lineIdx, this.text.length - this.lineStartOffsetByLineIdx[lineIdx]);
114-
}
115-
116-
getLineLength(lineNumber: number): number {
117-
return this.lineEndOffsetByLineIdx[lineNumber - 1] - this.lineStartOffsetByLineIdx[lineNumber - 1];
118-
}
119-
}
7+
import { TextEdit, TextReplacement } from '../edits/textEdit.js';
8+
import { _setPositionOffsetTransformerDependencies } from './positionToOffsetImpl.js';
9+
import { TextLength } from './textLength.js';
10+
11+
export { PositionOffsetTransformerBase, PositionOffsetTransformer } from './positionToOffsetImpl.js';
12+
13+
_setPositionOffsetTransformerDependencies({
14+
StringEdit: StringEdit,
15+
StringReplacement: StringReplacement,
16+
TextReplacement: TextReplacement,
17+
TextEdit: TextEdit,
18+
TextLength: TextLength,
19+
});
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { findLastIdxMonotonous } from '../../../../base/common/arraysFind.js';
7+
import { StringEdit, StringReplacement } from '../edits/stringEdit.js';
8+
import { OffsetRange } from '../ranges/offsetRange.js';
9+
import { Position } from '../position.js';
10+
import { Range } from '../range.js';
11+
import type { TextReplacement, TextEdit } from '../edits/textEdit.js';
12+
import type { TextLength } from '../text/textLength.js';
13+
14+
export abstract class PositionOffsetTransformerBase {
15+
abstract getOffset(position: Position): number;
16+
17+
getOffsetRange(range: Range): OffsetRange {
18+
return new OffsetRange(
19+
this.getOffset(range.getStartPosition()),
20+
this.getOffset(range.getEndPosition())
21+
);
22+
}
23+
24+
abstract getPosition(offset: number): Position;
25+
26+
getRange(offsetRange: OffsetRange): Range {
27+
return Range.fromPositions(
28+
this.getPosition(offsetRange.start),
29+
this.getPosition(offsetRange.endExclusive)
30+
);
31+
}
32+
33+
getStringEdit(edit: TextEdit): StringEdit {
34+
const edits = edit.replacements.map(e => this.getStringReplacement(e));
35+
return new Deps.deps.StringEdit(edits);
36+
}
37+
38+
getStringReplacement(edit: TextReplacement): StringReplacement {
39+
return new Deps.deps.StringReplacement(this.getOffsetRange(edit.range), edit.text);
40+
}
41+
42+
getSingleTextEdit(edit: StringReplacement): TextReplacement {
43+
return new Deps.deps.TextReplacement(this.getRange(edit.replaceRange), edit.newText);
44+
}
45+
46+
getTextEdit(edit: StringEdit): TextEdit {
47+
const edits = edit.replacements.map(e => this.getSingleTextEdit(e));
48+
return new Deps.deps.TextEdit(edits);
49+
}
50+
}
51+
52+
interface IDeps {
53+
StringEdit: typeof StringEdit;
54+
StringReplacement: typeof StringReplacement;
55+
TextReplacement: typeof TextReplacement;
56+
TextEdit: typeof TextEdit;
57+
TextLength: typeof TextLength;
58+
}
59+
60+
class Deps {
61+
static _deps: IDeps | undefined = undefined;
62+
static get deps(): IDeps {
63+
if (!this._deps) {
64+
throw new Error('Dependencies not set. Call _setDependencies first.');
65+
}
66+
return this._deps;
67+
}
68+
}
69+
70+
/** This is to break circular module dependencies. */
71+
export function _setPositionOffsetTransformerDependencies(deps: IDeps): void {
72+
Deps._deps = deps;
73+
}
74+
75+
export class PositionOffsetTransformer extends PositionOffsetTransformerBase {
76+
private readonly lineStartOffsetByLineIdx: number[];
77+
private readonly lineEndOffsetByLineIdx: number[];
78+
79+
constructor(public readonly text: string) {
80+
super();
81+
82+
this.lineStartOffsetByLineIdx = [];
83+
this.lineEndOffsetByLineIdx = [];
84+
85+
this.lineStartOffsetByLineIdx.push(0);
86+
for (let i = 0; i < text.length; i++) {
87+
if (text.charAt(i) === '\n') {
88+
this.lineStartOffsetByLineIdx.push(i + 1);
89+
if (i > 0 && text.charAt(i - 1) === '\r') {
90+
this.lineEndOffsetByLineIdx.push(i - 1);
91+
} else {
92+
this.lineEndOffsetByLineIdx.push(i);
93+
}
94+
}
95+
}
96+
this.lineEndOffsetByLineIdx.push(text.length);
97+
}
98+
99+
override getOffset(position: Position): number {
100+
const valPos = this._validatePosition(position);
101+
return this.lineStartOffsetByLineIdx[valPos.lineNumber - 1] + valPos.column - 1;
102+
}
103+
104+
private _validatePosition(position: Position): Position {
105+
if (position.lineNumber < 1) {
106+
return new Position(1, 1);
107+
}
108+
const lineCount = this.textLength.lineCount + 1;
109+
if (position.lineNumber > lineCount) {
110+
const lineLength = this.getLineLength(lineCount);
111+
return new Position(lineCount, lineLength + 1);
112+
}
113+
if (position.column < 1) {
114+
return new Position(position.lineNumber, 1);
115+
}
116+
const lineLength = this.getLineLength(position.lineNumber);
117+
if (position.column - 1 > lineLength) {
118+
return new Position(position.lineNumber, lineLength + 1);
119+
}
120+
return position;
121+
}
122+
123+
override getPosition(offset: number): Position {
124+
const idx = findLastIdxMonotonous(this.lineStartOffsetByLineIdx, i => i <= offset);
125+
const lineNumber = idx + 1;
126+
const column = offset - this.lineStartOffsetByLineIdx[idx] + 1;
127+
return new Position(lineNumber, column);
128+
}
129+
130+
getTextLength(offsetRange: OffsetRange): TextLength {
131+
return Deps.deps.TextLength.ofRange(this.getRange(offsetRange));
132+
}
133+
134+
get textLength(): TextLength {
135+
const lineIdx = this.lineStartOffsetByLineIdx.length - 1;
136+
return new Deps.deps.TextLength(lineIdx, this.text.length - this.lineStartOffsetByLineIdx[lineIdx]);
137+
}
138+
139+
getLineLength(lineNumber: number): number {
140+
return this.lineEndOffsetByLineIdx[lineNumber - 1] - this.lineStartOffsetByLineIdx[lineNumber - 1];
141+
}
142+
}

src/vs/editor/common/model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { IModelContentChange, IModelContentChangedEvent, IModelDecorationsChange
2323
import { IGuidesTextModelPart } from './textModelGuides.js';
2424
import { ITokenizationTextModelPart } from './tokenizationTextModelPart.js';
2525
import { UndoRedoGroup } from '../../platform/undoRedo/common/undoRedo.js';
26-
import { TokenArray } from './tokens/tokenArray.js';
26+
import { TokenArray } from './tokens/lineTokens.js';
2727
import { IEditorModel } from './editorCommon.js';
2828
import { TextModelEditReason } from './textModelEditReason.js';
2929

src/vs/editor/common/model/textModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { ITokenizationTextModelPart } from '../tokenizationTextModelPart.js';
4646
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
4747
import { IColorTheme } from '../../../platform/theme/common/themeService.js';
4848
import { IUndoRedoService, ResourceEditStackSnapshot, UndoRedoGroup } from '../../../platform/undoRedo/common/undoRedo.js';
49-
import { TokenArray } from '../tokens/tokenArray.js';
49+
import { TokenArray } from '../tokens/lineTokens.js';
5050
import { SetWithKey } from '../../../base/common/collections.js';
5151
import { TextModelEditReason } from '../textModelEditReason.js';
5252

0 commit comments

Comments
 (0)