Spaces:
Sleeping
Sleeping
| // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. | |
| // See LICENSE in the project root for license information. | |
| /** | |
| * Efficiently references a range of text from a string buffer. | |
| */ | |
| export class TextRange { | |
| constructor(buffer, pos, end) { | |
| this.buffer = buffer; | |
| this.pos = pos; | |
| this.end = end; | |
| this._validateBounds(); | |
| } | |
| /** | |
| * Constructs a TextRange that corresponds to an entire string object. | |
| */ | |
| static fromString(buffer) { | |
| return new TextRange(buffer, 0, buffer.length); | |
| } | |
| /** | |
| * Constructs a TextRange that corresponds to an entire string object. | |
| */ | |
| static fromStringRange(buffer, pos, end) { | |
| return new TextRange(buffer, pos, end); | |
| } | |
| /** | |
| * Returns the length of the text range. | |
| * @remarks | |
| * This value is calculated as the `end` property minus the `pos` property. | |
| */ | |
| get length() { | |
| return this.end - this.pos; | |
| } | |
| /** | |
| * Constructs a TextRange that corresponds to a different range of an existing buffer. | |
| */ | |
| getNewRange(pos, end) { | |
| return new TextRange(this.buffer, pos, end); | |
| } | |
| /** | |
| * Returns true if the length of the range is zero. Note that the object reference may not | |
| * be equal to `TextRange.empty`, and the buffer may be different. | |
| */ | |
| isEmpty() { | |
| return this.pos === this.end; | |
| } | |
| /** | |
| * Returns the range from the associated string buffer. | |
| */ | |
| toString() { | |
| return this.buffer.substring(this.pos, this.end); | |
| } | |
| /** | |
| * Returns a debugging dump of the range, indicated via custom delimiters. | |
| * @remarks | |
| * For example if the delimiters are "[" and "]", and the range is 3..5 inside "1234567", | |
| * then the output would be "12[345]67". | |
| */ | |
| getDebugDump(posDelimiter, endDelimiter) { | |
| return (this.buffer.substring(0, this.pos) + | |
| posDelimiter + | |
| this.buffer.substring(this.pos, this.end) + | |
| endDelimiter + | |
| this.buffer.substring(this.end)); | |
| } | |
| /** | |
| * Calculates the line and column number for the specified offset into the buffer. | |
| * | |
| * @remarks | |
| * This is a potentially expensive operation. | |
| * | |
| * @param index - an integer offset | |
| * @param buffer - the buffer | |
| */ | |
| getLocation(index) { | |
| if (index < 0 || index > this.buffer.length) { | |
| // No match | |
| return { line: 0, column: 0 }; | |
| } | |
| // TODO: Consider caching or optimizing this somehow | |
| let line = 1; | |
| let column = 1; | |
| let currentIndex = 0; | |
| while (currentIndex < index) { | |
| const current = this.buffer[currentIndex]; | |
| ++currentIndex; | |
| if (current === '\r') { | |
| // CR | |
| // Ignore '\r' and assume it will always have an accompanying '\n' | |
| continue; | |
| } | |
| if (current === '\n') { | |
| // LF | |
| ++line; | |
| column = 1; | |
| } | |
| else { | |
| // NOTE: For consistency with the TypeScript compiler, a tab character is assumed | |
| // to advance by one column | |
| ++column; | |
| } | |
| } | |
| return { line, column }; | |
| } | |
| _validateBounds() { | |
| if (this.pos < 0) { | |
| throw new Error('TextRange.pos cannot be negative'); | |
| } | |
| if (this.end < 0) { | |
| throw new Error('TextRange.end cannot be negative'); | |
| } | |
| if (this.end < this.pos) { | |
| throw new Error('TextRange.end cannot be smaller than TextRange.pos'); | |
| } | |
| if (this.pos > this.buffer.length) { | |
| throw new Error('TextRange.pos cannot exceed the associated text buffer length'); | |
| } | |
| if (this.end > this.buffer.length) { | |
| throw new Error('TextRange.end cannot exceed the associated text buffer length'); | |
| } | |
| } | |
| } | |
| /** | |
| * Used to represent an empty or unknown range. | |
| */ | |
| TextRange.empty = new TextRange('', 0, 0); | |
| //# sourceMappingURL=TextRange.js.map |