Add method on host to get DocumentPositionMapper so it can be cached.

This commit is contained in:
Sheetal Nandi
2018-11-16 10:15:51 -08:00
parent 0dad79e8b3
commit 12428d45c0
13 changed files with 219 additions and 89 deletions

View File

@@ -503,6 +503,66 @@ namespace ts.server {
return this.getLanguageService().getSourceMapper();
}
/*@internal*/
getDocumentPositionMapper(fileName: string): DocumentPositionMapper | undefined {
const declarationInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
if (!declarationInfo) return undefined;
declarationInfo.getSnapshot(); // Ensure synchronized
const existingMapper = declarationInfo.textStorage.mapper;
if (existingMapper !== undefined) {
return existingMapper ? existingMapper : undefined;
}
// Create the mapper
declarationInfo.mapInfo = undefined;
const mapper = getDocumentPositionMapper({
getCanonicalFileName: this.projectService.toCanonicalFileName,
log: s => this.log(s),
readMapFile: f => this.readMapFile(f, declarationInfo),
getSourceFileLike: f => this.getSourceFileLike(f)
}, declarationInfo.fileName, declarationInfo.textStorage.getLineInfo());
declarationInfo.textStorage.mapper = mapper || false;
return mapper;
}
private readMapFile(fileName: string, declarationInfo: ScriptInfo) {
const mapInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
if (!mapInfo) return undefined;
declarationInfo.mapInfo = mapInfo;
const snap = mapInfo.getSnapshot();
return snap.getText(0, snap.getLength());
}
/*@internal*/
getSourceFileLike(fileName: string) {
const path = this.toPath(fileName);
const sourceFile = this.getSourceFile(path);
if (sourceFile && sourceFile.resolvedPath === path) return sourceFile;
// Need to look for other files.
const info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
if (!info) return undefined;
// Key doesnt matter since its only for text and lines
if (info.cacheSourceFile) return info.cacheSourceFile.sourceFile;
if (info.textStorage.sourceFileLike) return info.textStorage.sourceFileLike;
info.textStorage.sourceFileLike = {
get text() {
Debug.fail("shouldnt need text");
return "";
},
getLineAndCharacterOfPosition: pos => {
const lineOffset = info.positionToLineOffset(pos);
return { line: lineOffset.line - 1, character: lineOffset.offset - 1 };
},
getPositionOfLineAndCharacter: (line, character) => info.lineOffsetToPosition(line + 1, character + 1)
};
return info.textStorage.sourceFileLike;
}
private shouldEmitFile(scriptInfo: ScriptInfo) {
return scriptInfo && !scriptInfo.isDynamicOrHasMixedContent();
}

View File

@@ -46,6 +46,9 @@ namespace ts.server {
*/
private pendingReloadFromDisk = false;
mapper: DocumentPositionMapper | false | undefined = false;
sourceFileLike: SourceFileLike | undefined;
constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath, initialVersion: ScriptInfoVersion | undefined, private readonly info: ScriptInfo) {
this.version = initialVersion || { svc: 0, text: 0 };
}
@@ -70,6 +73,8 @@ namespace ts.server {
this.text = newText;
this.lineMap = undefined;
this.fileSize = undefined;
this.mapper = undefined;
this.sourceFileLike = undefined;
this.version.text++;
}
@@ -79,6 +84,8 @@ namespace ts.server {
this.text = undefined;
this.lineMap = undefined;
this.fileSize = undefined;
this.mapper = undefined;
this.sourceFileLike = undefined;
}
/**
@@ -156,8 +163,8 @@ namespace ts.server {
: ScriptSnapshot.fromString(this.getOrLoadText());
}
public getLineInfo(line: number): AbsolutePositionAndLineText {
return this.switchToScriptVersionCache().getLineInfo(line);
public getAbsolutePositionAndLineText(line: number): AbsolutePositionAndLineText {
return this.switchToScriptVersionCache().getAbsolutePositionAndLineText(line);
}
/**
* @param line 0 based index
@@ -246,6 +253,17 @@ namespace ts.server {
Debug.assert(!this.svc, "ScriptVersionCache should not be set");
return this.lineMap || (this.lineMap = computeLineStarts(this.getOrLoadText()));
}
getLineInfo(): LineInfo {
if (this.svc) {
return {
getLineCount: () => this.svc!.getLineCount(),
getLineText: line => this.svc!.getAbsolutePositionAndLineText(line + 1).lineText!
};
}
const lineMap = this.getLineMap();
return getLineInfo(this.text!, lineMap);
}
}
/*@internal*/
@@ -269,7 +287,7 @@ namespace ts.server {
/* @internal */
fileWatcher: FileWatcher | undefined;
private textStorage: TextStorage;
/* @internal */ textStorage: TextStorage;
/*@internal*/
readonly isDynamic: boolean;
@@ -284,6 +302,9 @@ namespace ts.server {
/*@internal*/
mTime?: number;
/*@internal*/
mapInfo?: ScriptInfo;
constructor(
private readonly host: ServerHost,
readonly fileName: NormalizedPath,
@@ -521,8 +542,8 @@ namespace ts.server {
}
/*@internal*/
getLineInfo(line: number): AbsolutePositionAndLineText {
return this.textStorage.getLineInfo(line);
getAbsolutePositionAndLineText(line: number): AbsolutePositionAndLineText {
return this.textStorage.getAbsolutePositionAndLineText(line);
}
editContent(start: number, end: number, newText: string): void {

View File

@@ -308,8 +308,8 @@ namespace ts.server {
return this._getSnapshot().version;
}
getLineInfo(line: number): AbsolutePositionAndLineText {
return this._getSnapshot().index.lineNumberToInfo(line);
getAbsolutePositionAndLineText(oneBasedLine: number): AbsolutePositionAndLineText {
return this._getSnapshot().index.lineNumberToInfo(oneBasedLine);
}
lineOffsetToPosition(line: number, column: number): number {
@@ -348,6 +348,10 @@ namespace ts.server {
}
}
getLineCount() {
return this._getSnapshot().index.getLineCount();
}
static fromString(script: string) {
const svc = new ScriptVersionCache();
const snap = new LineIndexSnapshot(0, svc, new LineIndex());
@@ -400,8 +404,12 @@ namespace ts.server {
return this.root.charOffsetToLineInfo(1, position);
}
getLineCount() {
return this.root.lineCount();
}
lineNumberToInfo(oneBasedLine: number): AbsolutePositionAndLineText {
const lineCount = this.root.lineCount();
const lineCount = this.getLineCount();
if (oneBasedLine <= lineCount) {
const { position, leaf } = this.root.lineNumberToInfo(oneBasedLine, 0);
return { absolutePosition: position, lineText: leaf && leaf.text };

View File

@@ -1474,7 +1474,7 @@ 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 { lineText, absolutePosition } = scriptInfo.getLineInfo(args.line);
const { lineText, absolutePosition } = scriptInfo.getAbsolutePositionAndLineText(args.line);
if (lineText && lineText.search("\\S") < 0) {
const preferredIndent = languageService.getIndentationAtPosition(file, position, formatOptions);
let hasIndent = 0;