Path: blob/main/extensions/copilot/src/platform/editing/common/abstractText.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Lazy } from '../../../util/vs/base/common/lazy';6import { Position as CorePos } from '../../../util/vs/editor/common/core/position';7import { OffsetRange } from '../../../util/vs/editor/common/core/ranges/offsetRange';8import { PositionOffsetTransformer } from '../../../util/vs/editor/common/core/text/positionToOffset';9import { Range, Position as VSCodePos } from '../../../vscodeTypes';10import { TextDocumentSnapshot } from './textDocumentSnapshot';1112/**13* Represents an immutable view of a string with line/column characteristics.14* Offers many methods to work with various data types (ranges, positions, offsets, ...).15*/16export abstract class AbstractDocument {17abstract getText(): string;1819abstract getTextInOffsetRange(offsetRange: OffsetRange): string;2021abstract getPositionAtOffset(offset: number): VSCodePos;2223abstract getOffsetAtPosition(position: VSCodePos): number;2425abstract getLineText(lineIndex: number): string;2627abstract getLineLength(lineIndex: number): number;2829abstract getLineCount(): number;3031rangeToOffsetRange(range: Range): OffsetRange {32return new OffsetRange(this.getOffsetAtPosition(range.start), this.getOffsetAtPosition(range.end));33}3435offsetRangeToRange(offsetRange: OffsetRange): Range {36return new Range(37this.getPositionAtOffset(offsetRange.start),38this.getPositionAtOffset(offsetRange.endExclusive),39);40}4142abstract getPositionOffsetTransformer(): PositionOffsetTransformer;4344get length() {45return this.getText().length;46}47}4849export interface AbstractDocumentWithLanguageId extends AbstractDocument {50readonly languageId: string;51}5253export class VsCodeTextDocument extends AbstractDocument implements AbstractDocumentWithLanguageId {54public readonly uri = this.document.uri;5556public readonly languageId = this.document.languageId;5758constructor(public readonly document: TextDocumentSnapshot) {59super();60}6162getLineText(lineIndex: number): string {63return this.document.lineAt(lineIndex).text;64}6566getLineLength(lineIndex: number): number {67return this.document.lineAt(lineIndex).text.length;68}6970getLineCount(): number {71return this.document.lineCount;72}7374getText(): string {75return this.document.getText();76}7778getTextInOffsetRange(offsetRange: OffsetRange): string {79return offsetRange.substring(this.document.getText());80}8182getPositionAtOffset(offset: number): VSCodePos {83return this.document.positionAt(offset);84}8586getOffsetAtPosition(position: VSCodePos): number {87return this.document.offsetAt(position);88}8990private readonly _transformer = new Lazy(() => new PositionOffsetTransformer(this.document.getText()));9192override getPositionOffsetTransformer() {93return this._transformer.value;94}95}9697export class StringTextDocument extends AbstractDocument {98private readonly _transformer = new PositionOffsetTransformer(this.value);99100constructor(101public readonly value: string,102) {103super();104}105106override getText(): string {107return this.value;108}109110getLineText(lineIndex: number): string {111const startOffset = this._transformer.getOffset(new CorePos(lineIndex + 1, 1));112const endOffset = startOffset + this.getLineLength(lineIndex);113return this.value.substring(startOffset, endOffset);114}115116getLineLength(lineIndex: number): number {117return this._transformer.getLineLength(lineIndex + 1);118}119120getLineCount(): number {121return this._transformer.textLength.lineCount + 1;122}123124override getTextInOffsetRange(offsetRange: OffsetRange): string {125return offsetRange.substring(this.value);126}127128override getPositionAtOffset(offset: number): VSCodePos {129return corePositionToVSCodePosition(this._transformer.getPosition(offset));130}131132override getOffsetAtPosition(position: VSCodePos): number {133position = this._validatePosition(position);134return this._transformer.getOffset(vsCodePositionToCorePosition(position));135}136137private _validatePosition(position: VSCodePos): VSCodePos {138if (position.line < 0) {139return new VSCodePos(0, 0);140}141const lineCount = this._transformer.textLength.lineCount + 1;142if (position.line >= lineCount) {143const lineLength = this._transformer.getLineLength(lineCount);144return new VSCodePos(lineCount - 1, lineLength);145}146if (position.character < 0) {147return new VSCodePos(position.line, 0);148}149const lineLength = this._transformer.getLineLength(position.line + 1);150if (position.character > lineLength) {151return new VSCodePos(position.line, lineLength);152}153return position;154}155156override getPositionOffsetTransformer() {157return this._transformer;158}159}160161export class StringTextDocumentWithLanguageId extends StringTextDocument implements AbstractDocumentWithLanguageId {162constructor(163value: string,164public readonly languageId: string,165) {166super(value);167}168}169170function corePositionToVSCodePosition(position: CorePos): VSCodePos {171return new VSCodePos(position.lineNumber - 1, position.column - 1);172}173174function vsCodePositionToCorePosition(position: VSCodePos): CorePos {175return new CorePos(position.line + 1, position.character + 1);176}177178179