Remove ILineInfo type (#17017)
This commit is contained in:
parent
bffde588cc
commit
91d7b22e6a
5 changed files with 100 additions and 130 deletions
|
@ -7,8 +7,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function lineColToPosition(lineIndex: server.LineIndex, line: number, col: number) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(line);
|
||||
return (lineInfo.offset + col - 1);
|
||||
return lineIndex.absolutePositionOfStartOfLine(line) + (col - 1);
|
||||
}
|
||||
|
||||
function validateEdit(lineIndex: server.LineIndex, sourceText: string, position: number, deleteLength: number, insertString: string): void {
|
||||
|
@ -298,20 +297,17 @@ and grew 1cm per day`;
|
|||
|
||||
it("Line/offset from pos", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
const lp = lineIndex.charOffsetToLineNumberAndPos(rsa[i]);
|
||||
const lp = lineIndex.positionToLineOffset(rsa[i]);
|
||||
const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
|
||||
assert.equal(lac.line + 1, lp.line, "Line number mismatch " + (lac.line + 1) + " " + lp.line + " " + i);
|
||||
assert.equal(lac.character, (lp.offset), "Charachter offset mismatch " + lac.character + " " + lp.offset + " " + i);
|
||||
assert.equal(lac.character, lp.offset - 1, "Character offset mismatch " + lac.character + " " + (lp.offset - 1) + " " + i);
|
||||
}
|
||||
});
|
||||
|
||||
it("Start pos from line", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
for (let j = 0; j < lines.length; j++) {
|
||||
const lineInfo = lineIndex.lineNumberToInfo(j + 1);
|
||||
const lineIndexOffset = lineInfo.offset;
|
||||
const lineMapOffset = lineMap[j];
|
||||
assert.equal(lineIndexOffset, lineMapOffset);
|
||||
assert.equal(lineIndex.absolutePositionOfStartOfLine(j + 1), lineMap[j]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -640,7 +640,7 @@ namespace ts.server.protocol {
|
|||
}
|
||||
|
||||
/**
|
||||
* Location in source code expressed as (one-based) line and character offset.
|
||||
* Location in source code expressed as (one-based) line and (one-based) column offset.
|
||||
*/
|
||||
export interface Location {
|
||||
line: number;
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace ts.server {
|
|||
: ScriptSnapshot.fromString(this.getOrLoadText());
|
||||
}
|
||||
|
||||
public getLineInfo(line: number) {
|
||||
public getLineInfo(line: number): AbsolutePositionAndLineText {
|
||||
return this.switchToScriptVersionCache().getSnapshot().index.lineNumberToInfo(line);
|
||||
}
|
||||
/**
|
||||
|
@ -75,16 +75,9 @@ namespace ts.server {
|
|||
return ts.createTextSpanFromBounds(start, end);
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
const lineInfo = index.lineNumberToInfo(line + 1);
|
||||
let len: number;
|
||||
if (lineInfo.leaf) {
|
||||
len = lineInfo.leaf.text.length;
|
||||
}
|
||||
else {
|
||||
const nextLineInfo = index.lineNumberToInfo(line + 2);
|
||||
len = nextLineInfo.offset - lineInfo.offset;
|
||||
}
|
||||
return ts.createTextSpan(lineInfo.offset, len);
|
||||
const { lineText, absolutePosition } = index.lineNumberToInfo(line + 1);
|
||||
const len = lineText !== undefined ? lineText.length : index.absolutePositionOfStartOfLine(line + 2) - absolutePosition;
|
||||
return ts.createTextSpan(absolutePosition, len);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,25 +88,17 @@ namespace ts.server {
|
|||
if (!this.svc) {
|
||||
return computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1);
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
|
||||
const lineInfo = index.lineNumberToInfo(line);
|
||||
// TODO: assert this offset is actually on the line
|
||||
return (lineInfo.offset + offset - 1);
|
||||
return this.svc.getSnapshot().index.absolutePositionOfStartOfLine(line) + (offset - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 1-based index
|
||||
* @param offset 1-based index
|
||||
*/
|
||||
positionToLineOffset(position: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
if (!this.svc) {
|
||||
const { line, character } = computeLineAndCharacterOfPosition(this.getLineMap(), position);
|
||||
return { line: line + 1, offset: character + 1 };
|
||||
}
|
||||
const index = this.svc.getSnapshot().index;
|
||||
const lineOffset = index.charOffsetToLineNumberAndPos(position);
|
||||
return { line: lineOffset.line, offset: lineOffset.offset + 1 };
|
||||
return this.svc.getSnapshot().index.positionToLineOffset(position);
|
||||
}
|
||||
|
||||
private getFileText(tempFileName?: string) {
|
||||
|
@ -334,7 +319,7 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
getLineInfo(line: number) {
|
||||
getLineInfo(line: number): AbsolutePositionAndLineText {
|
||||
return this.textStorage.getLineInfo(line);
|
||||
}
|
||||
|
||||
|
@ -364,11 +349,7 @@ namespace ts.server {
|
|||
return this.textStorage.lineOffsetToPosition(line, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line 1-based index
|
||||
* @param offset 1-based index
|
||||
*/
|
||||
positionToLineOffset(position: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
return this.textStorage.positionToLineOffset(position);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,13 @@ namespace ts.server {
|
|||
export interface LineCollection {
|
||||
charCount(): number;
|
||||
lineCount(): number;
|
||||
isLeaf(): boolean;
|
||||
isLeaf(): this is LineLeaf;
|
||||
walk(rangeStart: number, rangeLength: number, walkFns: ILineIndexWalker): void;
|
||||
}
|
||||
|
||||
export interface ILineInfo {
|
||||
line: number;
|
||||
offset: number;
|
||||
text?: string;
|
||||
leaf?: LineLeaf;
|
||||
export interface AbsolutePositionAndLineText {
|
||||
absolutePosition: number;
|
||||
lineText: string | undefined;
|
||||
}
|
||||
|
||||
export enum CharRangeSection {
|
||||
|
@ -397,22 +395,27 @@ namespace ts.server {
|
|||
// set this to true to check each edit for accuracy
|
||||
checkEdits = false;
|
||||
|
||||
charOffsetToLineNumberAndPos(charOffset: number) {
|
||||
return this.root.charOffsetToLineNumberAndPos(1, charOffset);
|
||||
absolutePositionOfStartOfLine(oneBasedLine: number): number {
|
||||
return this.lineNumberToInfo(oneBasedLine).absolutePosition;
|
||||
}
|
||||
|
||||
lineNumberToInfo(lineNumber: number): ILineInfo {
|
||||
positionToLineOffset(position: number): protocol.Location {
|
||||
const { oneBasedLine, zeroBasedColumn } = this.root.charOffsetToLineInfo(1, position);
|
||||
return { line: oneBasedLine, offset: zeroBasedColumn + 1 };
|
||||
}
|
||||
|
||||
private positionToColumnAndLineText(position: number): { zeroBasedColumn: number, lineText: string } {
|
||||
return this.root.charOffsetToLineInfo(1, position);
|
||||
}
|
||||
|
||||
lineNumberToInfo(oneBasedLine: number): AbsolutePositionAndLineText {
|
||||
const lineCount = this.root.lineCount();
|
||||
if (lineNumber <= lineCount) {
|
||||
const lineInfo = this.root.lineNumberToInfo(lineNumber, 0);
|
||||
lineInfo.line = lineNumber;
|
||||
return lineInfo;
|
||||
if (oneBasedLine <= lineCount) {
|
||||
const { position, leaf } = this.root.lineNumberToInfo(oneBasedLine, 0);
|
||||
return { absolutePosition: position, lineText: leaf && leaf.text };
|
||||
}
|
||||
else {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: this.root.charCount()
|
||||
};
|
||||
return { absolutePosition: this.root.charCount(), lineText: undefined };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,17 +505,12 @@ namespace ts.server {
|
|||
else if (deleteLength > 0) {
|
||||
// check whether last characters deleted are line break
|
||||
const e = pos + deleteLength;
|
||||
const lineInfo = this.charOffsetToLineNumberAndPos(e);
|
||||
if ((lineInfo && (lineInfo.offset === 0))) {
|
||||
const { zeroBasedColumn, lineText } = this.positionToColumnAndLineText(e);
|
||||
if (zeroBasedColumn === 0) {
|
||||
// move range end just past line that will merge with previous line
|
||||
deleteLength += lineInfo.text.length;
|
||||
deleteLength += lineText.length;
|
||||
// store text by appending to end of insertedText
|
||||
if (newText) {
|
||||
newText = newText + lineInfo.text;
|
||||
}
|
||||
else {
|
||||
newText = lineInfo.text;
|
||||
}
|
||||
newText = newText ? newText + lineText : lineText;
|
||||
}
|
||||
}
|
||||
if (pos < this.root.charCount()) {
|
||||
|
@ -676,90 +674,88 @@ namespace ts.server {
|
|||
}
|
||||
}
|
||||
|
||||
charOffsetToLineNumberAndPos(lineNumber: number, charOffset: number): ILineInfo {
|
||||
const childInfo = this.childFromCharOffset(lineNumber, charOffset);
|
||||
// Input position is relative to the start of this node.
|
||||
// Output line number is absolute.
|
||||
charOffsetToLineInfo(lineNumberAccumulator: number, relativePosition: number): { oneBasedLine: number, zeroBasedColumn: number, lineText: string | undefined } {
|
||||
const childInfo = this.childFromCharOffset(lineNumberAccumulator, relativePosition);
|
||||
if (!childInfo.child) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: charOffset,
|
||||
oneBasedLine: lineNumberAccumulator,
|
||||
zeroBasedColumn: relativePosition,
|
||||
lineText: undefined,
|
||||
};
|
||||
}
|
||||
else if (childInfo.childIndex < this.children.length) {
|
||||
if (childInfo.child.isLeaf()) {
|
||||
return {
|
||||
line: childInfo.lineNumber,
|
||||
offset: childInfo.charOffset,
|
||||
text: (<LineLeaf>(childInfo.child)).text,
|
||||
leaf: (<LineLeaf>(childInfo.child))
|
||||
oneBasedLine: childInfo.lineNumberAccumulator,
|
||||
zeroBasedColumn: childInfo.relativePosition,
|
||||
lineText: childInfo.child.text,
|
||||
};
|
||||
}
|
||||
else {
|
||||
const lineNode = <LineNode>(childInfo.child);
|
||||
return lineNode.charOffsetToLineNumberAndPos(childInfo.lineNumber, childInfo.charOffset);
|
||||
return lineNode.charOffsetToLineInfo(childInfo.lineNumberAccumulator, childInfo.relativePosition);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const lineInfo = this.lineNumberToInfo(this.lineCount(), 0);
|
||||
return { line: this.lineCount(), offset: lineInfo.leaf.charCount() };
|
||||
return { oneBasedLine: this.lineCount(), zeroBasedColumn: lineInfo.leaf.charCount(), lineText: undefined };
|
||||
}
|
||||
}
|
||||
|
||||
lineNumberToInfo(lineNumber: number, charOffset: number): ILineInfo {
|
||||
const childInfo = this.childFromLineNumber(lineNumber, charOffset);
|
||||
lineNumberToInfo(relativeOneBasedLine: number, positionAccumulator: number): { position: number, leaf: LineLeaf | undefined } {
|
||||
const childInfo = this.childFromLineNumber(relativeOneBasedLine, positionAccumulator);
|
||||
if (!childInfo.child) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: charOffset
|
||||
};
|
||||
return { position: positionAccumulator, leaf: undefined };
|
||||
}
|
||||
else if (childInfo.child.isLeaf()) {
|
||||
return {
|
||||
line: lineNumber,
|
||||
offset: childInfo.charOffset,
|
||||
text: (<LineLeaf>(childInfo.child)).text,
|
||||
leaf: (<LineLeaf>(childInfo.child))
|
||||
};
|
||||
return { position: childInfo.positionAccumulator, leaf: childInfo.child };
|
||||
}
|
||||
else {
|
||||
const lineNode = <LineNode>(childInfo.child);
|
||||
return lineNode.lineNumberToInfo(childInfo.relativeLineNumber, childInfo.charOffset);
|
||||
return lineNode.lineNumberToInfo(childInfo.relativeOneBasedLine, childInfo.positionAccumulator);
|
||||
}
|
||||
}
|
||||
|
||||
childFromLineNumber(lineNumber: number, charOffset: number) {
|
||||
/**
|
||||
* Input line number is relative to the start of this node.
|
||||
* Output line number is relative to the child.
|
||||
* positionAccumulator will be an absolute position once relativeLineNumber reaches 0.
|
||||
*/
|
||||
private childFromLineNumber(relativeOneBasedLine: number, positionAccumulator: number): { child: LineCollection, relativeOneBasedLine: number, positionAccumulator: number } {
|
||||
let child: LineCollection;
|
||||
let relativeLineNumber = lineNumber;
|
||||
let i: number;
|
||||
let len: number;
|
||||
for (i = 0, len = this.children.length; i < len; i++) {
|
||||
for (i = 0; i < this.children.length; i++) {
|
||||
child = this.children[i];
|
||||
const childLineCount = child.lineCount();
|
||||
if (childLineCount >= relativeLineNumber) {
|
||||
if (childLineCount >= relativeOneBasedLine) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
relativeLineNumber -= childLineCount;
|
||||
charOffset += child.charCount();
|
||||
relativeOneBasedLine -= childLineCount;
|
||||
positionAccumulator += child.charCount();
|
||||
}
|
||||
}
|
||||
return { child, childIndex: i, relativeLineNumber, charOffset };
|
||||
return { child, relativeOneBasedLine, positionAccumulator };
|
||||
}
|
||||
|
||||
childFromCharOffset(lineNumber: number, charOffset: number) {
|
||||
private childFromCharOffset(lineNumberAccumulator: number, relativePosition: number
|
||||
): { child: LineCollection, childIndex: number, relativePosition: number, lineNumberAccumulator: number } {
|
||||
let child: LineCollection;
|
||||
let i: number;
|
||||
let len: number;
|
||||
for (i = 0, len = this.children.length; i < len; i++) {
|
||||
child = this.children[i];
|
||||
if (child.charCount() > charOffset) {
|
||||
if (child.charCount() > relativePosition) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
charOffset -= child.charCount();
|
||||
lineNumber += child.lineCount();
|
||||
relativePosition -= child.charCount();
|
||||
lineNumberAccumulator += child.lineCount();
|
||||
}
|
||||
}
|
||||
return { child, childIndex: i, charOffset, lineNumber };
|
||||
return { child, childIndex: i, relativePosition, lineNumberAccumulator };
|
||||
}
|
||||
|
||||
private splitAfter(childIndex: number) {
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace ts.server {
|
|||
|
||||
interface FileStart {
|
||||
file: string;
|
||||
start: ILineInfo;
|
||||
start: protocol.Location;
|
||||
}
|
||||
|
||||
function compareNumber(a: number, b: number) {
|
||||
|
@ -84,15 +84,15 @@ namespace ts.server {
|
|||
};
|
||||
}
|
||||
|
||||
function convertToILineInfo(lineAndCharacter: LineAndCharacter): ILineInfo {
|
||||
function convertToLocation(lineAndCharacter: LineAndCharacter): protocol.Location {
|
||||
return { line: lineAndCharacter.line + 1, offset: lineAndCharacter.character + 1 };
|
||||
}
|
||||
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: true): protocol.DiagnosticWithFileName;
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: false): protocol.Diagnostic;
|
||||
function formatConfigFileDiag(diag: ts.Diagnostic, includeFileName: boolean): protocol.Diagnostic | protocol.DiagnosticWithFileName {
|
||||
const start = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start));
|
||||
const end = diag.file && convertToILineInfo(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
|
||||
const start = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start));
|
||||
const end = diag.file && convertToLocation(getLineAndCharacterOfPosition(diag.file, diag.start + diag.length));
|
||||
const text = ts.flattenDiagnosticMessageText(diag.messageText, "\n");
|
||||
const { code, source } = diag;
|
||||
const category = DiagnosticCategory[diag.category].toLowerCase();
|
||||
|
@ -555,8 +555,8 @@ namespace ts.server {
|
|||
length: d.length,
|
||||
category: DiagnosticCategory[d.category].toLowerCase(),
|
||||
code: d.code,
|
||||
startLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start)),
|
||||
endLocation: d.file && convertToILineInfo(getLineAndCharacterOfPosition(d.file, d.start + d.length))
|
||||
startLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start)),
|
||||
endLocation: d.file && convertToLocation(getLineAndCharacterOfPosition(d.file, d.start + d.length))
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1131,32 +1131,29 @@ namespace ts.server {
|
|||
// only to the previous line. If all this is true, then
|
||||
// add edits necessary to properly indent the current line.
|
||||
if ((args.key === "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
|
||||
const lineInfo = scriptInfo.getLineInfo(args.line);
|
||||
if (lineInfo && (lineInfo.leaf) && (lineInfo.leaf.text)) {
|
||||
const lineText = lineInfo.leaf.text;
|
||||
if (lineText.search("\\S") < 0) {
|
||||
const preferredIndent = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, formatOptions);
|
||||
let hasIndent = 0;
|
||||
let i: number, len: number;
|
||||
for (i = 0, len = lineText.length; i < len; i++) {
|
||||
if (lineText.charAt(i) === " ") {
|
||||
hasIndent++;
|
||||
}
|
||||
else if (lineText.charAt(i) === "\t") {
|
||||
hasIndent += formatOptions.tabSize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
const { lineText, absolutePosition } = scriptInfo.getLineInfo(args.line);
|
||||
if (lineText && lineText.search("\\S") < 0) {
|
||||
const preferredIndent = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, formatOptions);
|
||||
let hasIndent = 0;
|
||||
let i: number, len: number;
|
||||
for (i = 0, len = lineText.length; i < len; i++) {
|
||||
if (lineText.charAt(i) === " ") {
|
||||
hasIndent++;
|
||||
}
|
||||
// i points to the first non whitespace character
|
||||
if (preferredIndent !== hasIndent) {
|
||||
const firstNoWhiteSpacePosition = lineInfo.offset + i;
|
||||
edits.push({
|
||||
span: ts.createTextSpanFromBounds(lineInfo.offset, firstNoWhiteSpacePosition),
|
||||
newText: formatting.getIndentationString(preferredIndent, formatOptions)
|
||||
});
|
||||
else if (lineText.charAt(i) === "\t") {
|
||||
hasIndent += formatOptions.tabSize;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// i points to the first non whitespace character
|
||||
if (preferredIndent !== hasIndent) {
|
||||
const firstNoWhiteSpacePosition = absolutePosition + i;
|
||||
edits.push({
|
||||
span: ts.createTextSpanFromBounds(absolutePosition, firstNoWhiteSpacePosition),
|
||||
newText: formatting.getIndentationString(preferredIndent, formatOptions)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1514,7 +1511,7 @@ namespace ts.server {
|
|||
|
||||
if (simplifiedResult) {
|
||||
const file = result.renameFilename;
|
||||
let location: ILineInfo | undefined = undefined;
|
||||
let location: protocol.Location | undefined;
|
||||
if (file !== undefined && result.renameLocation !== undefined) {
|
||||
const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(file));
|
||||
location = renameScriptInfo.positionToLineOffset(result.renameLocation);
|
||||
|
|
Loading…
Reference in a new issue