Add handling of hard tabs in server buffers. Change message protocol to

pass locations as line/offset pairs instead of line/column pairs, where
offset is a 1-based character offset from the beginning of the line.
Offset will be equal to column if the line contains no tabs.  If the
line contains tabs, offset will be less than or equal to column,
depending on how many tabs are before the offset.  Also added tab size
and indent size to file open message.
This commit is contained in:
steveluc
2015-03-17 22:58:12 -07:00
parent afc142c0f5
commit 34e612c9fc
4 changed files with 167 additions and 181 deletions

View File

@@ -46,21 +46,21 @@ module ts.server {
return lineMap;
}
private lineColToPosition(fileName: string, lineCol: protocol.Location): number {
return ts.computePositionOfLineAndCharacter(this.getLineMap(fileName), lineCol.line - 1, lineCol.col - 1);
private lineOffsetToPosition(fileName: string, lineOffset: protocol.Location): number {
return ts.computePositionOfLineAndCharacter(this.getLineMap(fileName), lineOffset.line - 1, lineOffset.offset - 1);
}
private positionToOneBasedLineCol(fileName: string, position: number): protocol.Location {
var lineCol = ts.computeLineAndCharacterOfPosition(this.getLineMap(fileName), position);
private positionToOneBasedLineOffset(fileName: string, position: number): protocol.Location {
var lineOffset = ts.computeLineAndCharacterOfPosition(this.getLineMap(fileName), position);
return {
line: lineCol.line + 1,
col: lineCol.character + 1
line: lineOffset.line + 1,
offset: lineOffset.character + 1
};
}
private convertCodeEditsToTextChange(fileName: string, codeEdit: protocol.CodeEdit): ts.TextChange {
var start = this.lineColToPosition(fileName, codeEdit.start);
var end = this.lineColToPosition(fileName, codeEdit.end);
var start = this.lineOffsetToPosition(fileName, codeEdit.start);
var end = this.lineOffsetToPosition(fileName, codeEdit.end);
return {
span: ts.createTextSpanFromBounds(start, end),
@@ -134,15 +134,15 @@ module ts.server {
// clear the line map after an edit
this.lineMaps[fileName] = undefined;
var lineCol = this.positionToOneBasedLineCol(fileName, start);
var endLineCol = this.positionToOneBasedLineCol(fileName, end);
var lineOffset = this.positionToOneBasedLineOffset(fileName, start);
var endLineOffset = this.positionToOneBasedLineOffset(fileName, end);
var args: protocol.ChangeRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
endLine: endLineCol.line,
endCol: endLineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
endLine: endLineOffset.line,
endOffset: endLineOffset.offset,
insertString: newText
};
@@ -150,18 +150,18 @@ module ts.server {
}
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.FileLocationRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col
line: lineOffset.line,
offset: lineOffset.offset
};
var request = this.processRequest<protocol.QuickInfoRequest>(CommandNames.Quickinfo, args);
var response = this.processResponse<protocol.QuickInfoResponse>(request);
var start = this.lineColToPosition(fileName, response.body.start);
var end = this.lineColToPosition(fileName, response.body.end);
var start = this.lineOffsetToPosition(fileName, response.body.start);
var end = this.lineOffsetToPosition(fileName, response.body.end);
return {
kind: response.body.kind,
@@ -173,11 +173,11 @@ module ts.server {
}
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.CompletionsRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
prefix: undefined
};
@@ -194,11 +194,11 @@ module ts.server {
}
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.CompletionDetailsRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
entryNames: [entryName]
};
@@ -219,8 +219,8 @@ module ts.server {
return response.body.map(entry => {
var fileName = entry.file;
var start = this.lineColToPosition(fileName, entry.start);
var end = this.lineColToPosition(fileName, entry.end);
var start = this.lineOffsetToPosition(fileName, entry.start);
var end = this.lineOffsetToPosition(fileName, entry.end);
return {
name: entry.name,
@@ -237,14 +237,14 @@ module ts.server {
}
getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions): ts.TextChange[] {
var startLineCol = this.positionToOneBasedLineCol(fileName, start);
var endLineCol = this.positionToOneBasedLineCol(fileName, end);
var startLineOffset = this.positionToOneBasedLineOffset(fileName, start);
var endLineOffset = this.positionToOneBasedLineOffset(fileName, end);
var args: protocol.FormatRequestArgs = {
file: fileName,
line: startLineCol.line,
col: startLineCol.col,
endLine: endLineCol.line,
endCol: endLineCol.col,
line: startLineOffset.line,
offset: startLineOffset.offset,
endLine: endLineOffset.line,
endOffset: endLineOffset.offset,
};
// TODO: handle FormatCodeOptions
@@ -259,11 +259,11 @@ module ts.server {
}
getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): ts.TextChange[] {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.FormatOnKeyRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
key: key
};
@@ -275,11 +275,11 @@ module ts.server {
}
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.FileLocationRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
};
var request = this.processRequest<protocol.DefinitionRequest>(CommandNames.Definition, args);
@@ -287,8 +287,8 @@ module ts.server {
return response.body.map(entry => {
var fileName = entry.file;
var start = this.lineColToPosition(fileName, entry.start);
var end = this.lineColToPosition(fileName, entry.end);
var start = this.lineOffsetToPosition(fileName, entry.start);
var end = this.lineOffsetToPosition(fileName, entry.end);
return {
containerKind: "",
containerName: "",
@@ -301,11 +301,11 @@ module ts.server {
}
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.FileLocationRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
};
var request = this.processRequest<protocol.ReferencesRequest>(CommandNames.References, args);
@@ -313,8 +313,8 @@ module ts.server {
return response.body.refs.map(entry => {
var fileName = entry.file;
var start = this.lineColToPosition(fileName, entry.start);
var end = this.lineColToPosition(fileName, entry.end);
var start = this.lineOffsetToPosition(fileName, entry.start);
var end = this.lineOffsetToPosition(fileName, entry.end);
return {
fileName: fileName,
textSpan: ts.createTextSpanFromBounds(start, end),
@@ -340,11 +340,11 @@ module ts.server {
}
getRenameInfo(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameInfo {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.RenameRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
findInStrings,
findInComments
};
@@ -355,8 +355,8 @@ module ts.server {
response.body.locs.map((entry: protocol.SpanGroup) => {
var fileName = entry.file;
entry.locs.map((loc: protocol.TextSpan) => {
var start = this.lineColToPosition(fileName, loc.start);
var end = this.lineColToPosition(fileName, loc.end);
var start = this.lineOffsetToPosition(fileName, loc.start);
var end = this.lineOffsetToPosition(fileName, loc.end);
locations.push({
textSpan: ts.createTextSpanFromBounds(start, end),
fileName: fileName
@@ -400,7 +400,7 @@ module ts.server {
text: item.text,
kind: item.kind,
kindModifiers: item.kindModifiers || "",
spans: item.spans.map(span=> createTextSpanFromBounds(this.lineColToPosition(fileName, span.start), this.lineColToPosition(fileName, span.end))),
spans: item.spans.map(span=> createTextSpanFromBounds(this.lineOffsetToPosition(fileName, span.start), this.lineOffsetToPosition(fileName, span.end))),
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
indent: 0,
bolded: false,
@@ -444,19 +444,19 @@ module ts.server {
}
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] {
var lineCol = this.positionToOneBasedLineCol(fileName, position);
var lineOffset = this.positionToOneBasedLineOffset(fileName, position);
var args: protocol.FileLocationRequestArgs = {
file: fileName,
line: lineCol.line,
col: lineCol.col,
line: lineOffset.line,
offset: lineOffset.offset,
};
var request = this.processRequest<protocol.BraceRequest>(CommandNames.Brace, args);
var response = this.processResponse<protocol.BraceResponse>(request);
return response.body.map(entry => {
var start = this.lineColToPosition(fileName, entry.start);
var end = this.lineColToPosition(fileName, entry.end);
var start = this.lineOffsetToPosition(fileName, entry.start);
var end = this.lineOffsetToPosition(fileName, entry.end);
return {
start: start,
length: end - start,

View File

@@ -27,9 +27,13 @@ module ts.server {
this.svc = ScriptVersionCache.fromString(content);
}
setFormatOptions(tabSize: number, indentSize: number) {
this.formatCodeOptions.TabSize = tabSize;
this.formatCodeOptions.IndentSize = indentSize;
setFormatOptions(tabSize?: number, indentSize?: number) {
if (tabSize) {
this.formatCodeOptions.TabSize = tabSize;
}
if (indentSize) {
this.formatCodeOptions.IndentSize = indentSize;
}
}
close() {
@@ -160,15 +164,12 @@ module ts.server {
reloadScript(filename: string, tmpfilename: string, cb: () => any) {
var script = this.getScriptInfo(filename);
if (script) {
script.svc.reloadFromFile(tmpfilename, script.formatCodeOptions.TabSize, cb);
script.svc.reloadFromFile(tmpfilename, cb);
}
}
editScript(filename: string, start: number, end: number, newText: string) {
var script = this.getScriptInfo(filename);
if (newText && (newText.length > 0)) {
newText = expandTabs(newText, script.formatCodeOptions.TabSize);
}
if (script) {
script.editContent(start, end, newText);
return;
@@ -207,33 +208,33 @@ module ts.server {
}
else {
var nextLineInfo = index.lineNumberToInfo(line + 2);
len = nextLineInfo.col - lineInfo.col;
len = nextLineInfo.offset - lineInfo.offset;
}
return ts.createTextSpan(lineInfo.col, len);
return ts.createTextSpan(lineInfo.offset, len);
}
/**
* @param line 1 based index
* @param col 1 based index
* @param offset 1 based index
*/
lineColToPosition(filename: string, line: number, col: number): number {
lineOffsetToPosition(filename: string, line: number, offset: number): number {
var script: ScriptInfo = this.filenameToScript[filename];
var index = script.snap().index;
var lineInfo = index.lineNumberToInfo(line);
// TODO: assert this column is actually on the line
return (lineInfo.col + col - 1);
// TODO: assert this offset is actually on the line
return (lineInfo.offset + offset - 1);
}
/**
* @param line 1-based index
* @param col 1-based index
* @param offset 1-based index
*/
positionToLineCol(filename: string, position: number): ILineInfo {
positionToLineOffset(filename: string, position: number): ILineInfo {
var script: ScriptInfo = this.filenameToScript[filename];
var index = script.snap().index;
var lineCol = index.charOffsetToLineNumberAndPos(position);
return { line: lineCol.line, col: lineCol.col + 1 };
var lineOffset = index.charOffsetToLineNumberAndPos(position);
return { line: lineOffset.line, offset: lineOffset.offset + 1 };
}
}
@@ -372,12 +373,6 @@ module ts.server {
hostInfo: string;
}
export function expandTabs(text: string, tabSize: number) {
var spaces = generateSpaces(tabSize);
return text.replace(/\t/g, spaces);
}
export class ProjectService {
filenameToScriptInfo: ts.Map<ScriptInfo> = {};
// open, non-configured files in two lists
@@ -421,7 +416,7 @@ module ts.server {
}
else {
if (info && (!info.isOpen)) {
info.svc.reloadFromFile(info.fileName, info.formatCodeOptions.TabSize);
info.svc.reloadFromFile(info.fileName);
}
}
}
@@ -646,7 +641,7 @@ module ts.server {
/**
* @param filename is absolute pathname
*/
openFile(fileName: string, openedByClient: boolean, tabSize?: number) {
openFile(fileName: string, openedByClient: boolean) {
fileName = ts.normalizePath(fileName);
var info = ts.lookUp(this.filenameToScriptInfo, fileName);
if (!info) {
@@ -661,25 +656,11 @@ module ts.server {
}
if (content !== undefined) {
var indentSize: number;
if (!tabSize) {
tabSize = this.hostConfiguration.formatCodeOptions.TabSize;
indentSize = this.hostConfiguration.formatCodeOptions.IndentSize;
}
else {
indentSize = tabSize;
}
if (openedByClient) {
this.log("Expanding tabs for file " + fileName + " with tab size " + tabSize.toString());
content = expandTabs(content, tabSize);
}
info = new ScriptInfo(this.host, fileName, content, openedByClient);
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
info.fileWatcher = this.host.watchFile(fileName, _ => { this.watchedFileChanged(fileName); });
}
else {
info.setFormatOptions(tabSize, indentSize);
}
}
}
if (info) {
@@ -695,9 +676,9 @@ module ts.server {
* @param filename is absolute pathname
*/
openClientFile(filename: string, tabSize?: number) {
openClientFile(filename: string) {
// TODO: tsconfig check
var info = this.openFile(filename, true, tabSize);
var info = this.openFile(filename, true);
this.addOpenFile(info);
this.printProjects();
return info;
@@ -878,7 +859,7 @@ module ts.server {
export interface ILineInfo {
line: number;
col: number;
offset: number;
text?: string;
leaf?: LineLeaf;
}
@@ -1159,9 +1140,8 @@ module ts.server {
return this.currentVersion;
}
reloadFromFile(filename: string, tabSize: number, cb?: () => any) {
reloadFromFile(filename: string, cb?: () => any) {
var content = ts.sys.readFile(filename);
content = expandTabs(content, tabSize);
this.reload(content);
if (cb)
cb();
@@ -1272,7 +1252,7 @@ module ts.server {
getLineMapper() {
return ((line: number) => {
return this.index.lineNumberToInfo(line).col;
return this.index.lineNumberToInfo(line).offset;
});
}
@@ -1309,7 +1289,7 @@ module ts.server {
else {
return {
line: lineNumber,
col: this.root.charCount()
offset: this.root.charCount()
}
}
}
@@ -1395,7 +1375,7 @@ module ts.server {
// check whether last characters deleted are line break
var e = pos + deleteLength;
var lineInfo = this.charOffsetToLineNumberAndPos(e);
if ((lineInfo && (lineInfo.col == 0))) {
if ((lineInfo && (lineInfo.offset == 0))) {
// move range end just past line that will merge with previous line
deleteLength += lineInfo.text.length;
// store text by appending to end of insertedText
@@ -1571,14 +1551,14 @@ module ts.server {
if (!childInfo.child) {
return {
line: lineNumber,
col: charOffset,
offset: charOffset,
}
}
else if (childInfo.childIndex < this.children.length) {
if (childInfo.child.isLeaf()) {
return {
line: childInfo.lineNumber,
col: childInfo.charOffset,
offset: childInfo.charOffset,
text: (<LineLeaf>(childInfo.child)).text,
leaf: (<LineLeaf>(childInfo.child))
};
@@ -1590,7 +1570,7 @@ module ts.server {
}
else {
var lineInfo = this.lineNumberToInfo(this.lineCount(), 0);
return { line: this.lineCount(), col: lineInfo.leaf.charCount() };
return { line: this.lineCount(), offset: lineInfo.leaf.charCount() };
}
}
@@ -1599,13 +1579,13 @@ module ts.server {
if (!childInfo.child) {
return {
line: lineNumber,
col: charOffset
offset: charOffset
}
}
}
else if (childInfo.child.isLeaf()) {
return {
line: lineNumber,
col: childInfo.charOffset,
offset: childInfo.charOffset,
text: (<LineLeaf>(childInfo.child)).text,
leaf: (<LineLeaf>(childInfo.child))
}

View File

@@ -96,7 +96,7 @@ declare module ts.server.protocol {
/**
* Instances of this interface specify a location in a source file:
* (file, line, col), where line and column are 1-based.
* (file, line, character offset), where line and character offset are 1-based.
*/
export interface FileLocationRequestArgs extends FileRequestArgs {
/**
@@ -105,9 +105,9 @@ declare module ts.server.protocol {
line: number;
/**
* The column for the request (1-based).
* The character offset (on the line) for the request (1-based).
*/
col: number;
offset: number;
}
/**
@@ -126,11 +126,11 @@ declare module ts.server.protocol {
}
/**
* Location in source code expressed as (one-based) line and column.
* Location in source code expressed as (one-based) line and character offset.
*/
export interface Location {
line: number;
col: number;
offset: number;
}
/**
@@ -202,9 +202,9 @@ declare module ts.server.protocol {
symbolName: string;
/**
* The start column of the symbol (on the line provided by the references request).
* The start character offset of the symbol (on the line provided by the references request).
*/
symbolStartCol: number;
symbolStartOffset: number;
/**
* The full display name of the symbol.
@@ -339,6 +339,8 @@ declare module ts.server.protocol {
export interface OpenRequestArgs extends FileRequestArgs {
/** Initial tab size of file. */
tabSize?: number;
/** Number of spaces to indent during formatting */
indentSize?: number;
}
/**
@@ -424,9 +426,9 @@ declare module ts.server.protocol {
endLine: number;
/**
* Last column of range for which to format text in file.
* Character offset on last line of range for which to format text in file.
*/
endCol: number;
endOffset: number;
}
/**
@@ -805,7 +807,7 @@ declare module ts.server.protocol {
*/
export interface ChangeRequestArgs extends FormatRequestArgs {
/**
* Optional string to insert at location (file, line, col).
* Optional string to insert at location (file, line, offset).
*/
insertString?: string;
}
@@ -829,7 +831,7 @@ declare module ts.server.protocol {
/**
* Brace matching request; value of command field is "brace".
* Return response giving the file locations of matching braces
* found in file at location line, col.
* found in file at location line, offset.
*/
export interface BraceRequest extends FileLocationRequest {
}

View File

@@ -44,7 +44,7 @@ module ts.server {
else if (a.file == b.file) {
var n = compareNumber(a.start.line, b.start.line);
if (n == 0) {
return compareNumber(a.start.col, b.start.col);
return compareNumber(a.start.offset, b.start.offset);
}
else return n;
}
@@ -55,8 +55,8 @@ module ts.server {
function formatDiag(fileName: string, project: Project, diag: ts.Diagnostic) {
return {
start: project.compilerService.host.positionToLineCol(fileName, diag.start),
end: project.compilerService.host.positionToLineCol(fileName, diag.start + diag.length),
start: project.compilerService.host.positionToLineOffset(fileName, diag.start),
end: project.compilerService.host.positionToLineOffset(fileName, diag.start + diag.length),
text: ts.flattenDiagnosticMessageText(diag.messageText, "\n")
};
}
@@ -260,7 +260,7 @@ module ts.server {
}
}
getDefinition(line: number, col: number, fileName: string): protocol.FileSpan[] {
getDefinition(line: number, offset: number, fileName: string): protocol.FileSpan[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
@@ -268,7 +268,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var definitions = compilerService.languageService.getDefinitionAtPosition(file, position);
if (!definitions) {
@@ -277,12 +277,12 @@ module ts.server {
return definitions.map(def => ({
file: def.fileName,
start: compilerService.host.positionToLineCol(def.fileName, def.textSpan.start),
end: compilerService.host.positionToLineCol(def.fileName, ts.textSpanEnd(def.textSpan))
start: compilerService.host.positionToLineOffset(def.fileName, def.textSpan.start),
end: compilerService.host.positionToLineOffset(def.fileName, ts.textSpanEnd(def.textSpan))
}));
}
getRenameLocations(line: number, col: number, fileName: string,findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
getRenameLocations(line: number, offset: number, fileName: string,findInComments: boolean, findInStrings: boolean): protocol.RenameResponseBody {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
@@ -290,7 +290,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var renameInfo = compilerService.languageService.getRenameInfo(file, position);
if (!renameInfo) {
return undefined;
@@ -310,8 +310,8 @@ module ts.server {
var bakedRenameLocs = renameLocations.map(location => (<protocol.FileSpan>{
file: location.fileName,
start: compilerService.host.positionToLineCol(location.fileName, location.textSpan.start),
end: compilerService.host.positionToLineCol(location.fileName, ts.textSpanEnd(location.textSpan)),
start: compilerService.host.positionToLineOffset(location.fileName, location.textSpan.start),
end: compilerService.host.positionToLineOffset(location.fileName, ts.textSpanEnd(location.textSpan)),
})).sort((a, b) => {
if (a.file < b.file) {
return -1;
@@ -328,7 +328,7 @@ module ts.server {
return -1;
}
else {
return b.start.col - a.start.col;
return b.start.offset - a.start.offset;
}
}
}).reduce<protocol.SpanGroup[]>((accum: protocol.SpanGroup[], cur: protocol.FileSpan) => {
@@ -350,7 +350,7 @@ module ts.server {
return { info: renameInfo, locs: bakedRenameLocs };
}
getReferences(line: number, col: number, fileName: string): protocol.ReferencesResponseBody {
getReferences(line: number, offset: number, fileName: string): protocol.ReferencesResponseBody {
// TODO: get all projects for this file; report refs for all projects deleting duplicates
// can avoid duplicates by eliminating same ref file from subsequent projects
var file = ts.normalizePath(fileName);
@@ -360,7 +360,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var references = compilerService.languageService.getReferencesAtPosition(file, position);
if (!references) {
@@ -374,10 +374,10 @@ module ts.server {
var displayString = ts.displayPartsToString(nameInfo.displayParts);
var nameSpan = nameInfo.textSpan;
var nameColStart = compilerService.host.positionToLineCol(file, nameSpan.start).col;
var nameColStart = compilerService.host.positionToLineOffset(file, nameSpan.start).offset;
var nameText = compilerService.host.getScriptSnapshot(file).getText(nameSpan.start, ts.textSpanEnd(nameSpan));
var bakedRefs: protocol.ReferencesResponseItem[] = references.map((ref) => {
var start = compilerService.host.positionToLineCol(ref.fileName, ref.textSpan.start);
var start = compilerService.host.positionToLineOffset(ref.fileName, ref.textSpan.start);
var refLineSpan = compilerService.host.lineToTextSpan(ref.fileName, start.line - 1);
var snap = compilerService.host.getScriptSnapshot(ref.fileName);
var lineText = snap.getText(refLineSpan.start, ts.textSpanEnd(refLineSpan)).replace(/\r|\n/g, "");
@@ -385,24 +385,27 @@ module ts.server {
file: ref.fileName,
start: start,
lineText: lineText,
end: compilerService.host.positionToLineCol(ref.fileName, ts.textSpanEnd(ref.textSpan)),
end: compilerService.host.positionToLineOffset(ref.fileName, ts.textSpanEnd(ref.textSpan)),
isWriteAccess: ref.isWriteAccess
};
}).sort(compareFileStart);
return {
refs: bakedRefs,
symbolName: nameText,
symbolStartCol: nameColStart,
symbolStartOffset: nameColStart,
symbolDisplayString: displayString
};
}
openClientFile(fileName: string, tabSize?: number) {
openClientFile(fileName: string, tabSize?: number, indentSize?: number) {
var file = ts.normalizePath(fileName);
this.projectService.openClientFile(file, tabSize);
var info = this.projectService.openClientFile(file);
if (info) {
info.setFormatOptions(tabSize, indentSize);
}
}
getQuickInfo(line: number, col: number, fileName: string): protocol.QuickInfoResponseBody {
getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
@@ -410,7 +413,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var quickInfo = compilerService.languageService.getQuickInfoAtPosition(file, position);
if (!quickInfo) {
return undefined;
@@ -421,14 +424,14 @@ module ts.server {
return {
kind: quickInfo.kind,
kindModifiers: quickInfo.kindModifiers,
start: compilerService.host.positionToLineCol(file, quickInfo.textSpan.start),
end: compilerService.host.positionToLineCol(file, ts.textSpanEnd(quickInfo.textSpan)),
start: compilerService.host.positionToLineOffset(file, quickInfo.textSpan.start),
end: compilerService.host.positionToLineOffset(file, ts.textSpanEnd(quickInfo.textSpan)),
displayString: displayString,
documentation: docString,
};
}
getFormattingEditsForRange(line: number, col: number, endLine: number, endCol: number, fileName: string): protocol.CodeEdit[] {
getFormattingEditsForRange(line: number, offset: number, endLine: number, endOffset: number, fileName: string): protocol.CodeEdit[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (!project) {
@@ -436,8 +439,8 @@ module ts.server {
}
var compilerService = project.compilerService;
var startPosition = compilerService.host.lineColToPosition(file, line, col);
var endPosition = compilerService.host.lineColToPosition(file, endLine, endCol);
var startPosition = compilerService.host.lineOffsetToPosition(file, line, offset);
var endPosition = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
// TODO: avoid duplicate code (with formatonkey)
var edits = compilerService.languageService.getFormattingEditsForRange(file, startPosition, endPosition,
@@ -448,14 +451,14 @@ module ts.server {
return edits.map((edit) => {
return {
start: compilerService.host.positionToLineCol(file, edit.span.start),
end: compilerService.host.positionToLineCol(file, ts.textSpanEnd(edit.span)),
start: compilerService.host.positionToLineOffset(file, edit.span.start),
end: compilerService.host.positionToLineOffset(file, ts.textSpanEnd(edit.span)),
newText: edit.newText ? edit.newText : ""
};
});
}
getFormattingEditsAfterKeystroke(line: number, col: number, key: string, fileName: string): protocol.CodeEdit[] {
getFormattingEditsAfterKeystroke(line: number, offset: number, key: string, fileName: string): protocol.CodeEdit[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
@@ -464,7 +467,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var formatOptions = this.projectService.getFormatCodeOptions(file);
var edits = compilerService.languageService.getFormattingEditsAfterKeystroke(file, position, key,
formatOptions);
@@ -519,16 +522,16 @@ module ts.server {
return edits.map((edit) => {
return {
start: compilerService.host.positionToLineCol(file,
start: compilerService.host.positionToLineOffset(file,
edit.span.start),
end: compilerService.host.positionToLineCol(file,
end: compilerService.host.positionToLineOffset(file,
ts.textSpanEnd(edit.span)),
newText: edit.newText ? edit.newText : ""
};
});
}
getCompletions(line: number, col: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
getCompletions(line: number, offset: number, prefix: string, fileName: string): protocol.CompletionEntry[] {
if (!prefix) {
prefix = "";
}
@@ -539,7 +542,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var completions = compilerService.languageService.getCompletionsAtPosition(file, position);
if (!completions) {
@@ -554,7 +557,7 @@ module ts.server {
}, []);
}
getCompletionEntryDetails(line: number, col: number,
getCompletionEntryDetails(line: number, offset: number,
entryNames: string[], fileName: string): protocol.CompletionEntryDetails[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
@@ -563,7 +566,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
return entryNames.reduce((accum: protocol.CompletionEntryDetails[], entryName: string) => {
var details = compilerService.languageService.getCompletionEntryDetails(file, position, entryName);
@@ -589,13 +592,13 @@ module ts.server {
}
}
change(line: number, col: number, endLine: number, endCol: number, insertString: string, fileName: string) {
change(line: number, offset: number, endLine: number, endOffset: number, insertString: string, fileName: string) {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
if (project) {
var compilerService = project.compilerService;
var start = compilerService.host.lineColToPosition(file, line, col);
var end = compilerService.host.lineColToPosition(file, endLine, endCol);
var start = compilerService.host.lineOffsetToPosition(file, line, offset);
var end = compilerService.host.lineOffsetToPosition(file, endLine, endOffset);
if (start >= 0) {
compilerService.host.editScript(file, start, end, insertString);
this.changeSeq++;
@@ -644,8 +647,8 @@ module ts.server {
kind: item.kind,
kindModifiers: item.kindModifiers,
spans: item.spans.map(span => ({
start: compilerService.host.positionToLineCol(fileName, span.start),
end: compilerService.host.positionToLineCol(fileName, ts.textSpanEnd(span))
start: compilerService.host.positionToLineOffset(fileName, span.start),
end: compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(span))
})),
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems)
}));
@@ -681,8 +684,8 @@ module ts.server {
}
return navItems.map((navItem) => {
var start = compilerService.host.positionToLineCol(navItem.fileName, navItem.textSpan.start);
var end = compilerService.host.positionToLineCol(navItem.fileName, ts.textSpanEnd(navItem.textSpan));
var start = compilerService.host.positionToLineOffset(navItem.fileName, navItem.textSpan.start);
var end = compilerService.host.positionToLineOffset(navItem.fileName, ts.textSpanEnd(navItem.textSpan));
var bakedItem: protocol.NavtoItem = {
name: navItem.name,
kind: navItem.kind,
@@ -706,7 +709,7 @@ module ts.server {
});
}
getBraceMatching(line: number, col: number, fileName: string): protocol.TextSpan[] {
getBraceMatching(line: number, offset: number, fileName: string): protocol.TextSpan[] {
var file = ts.normalizePath(fileName);
var project = this.projectService.getProjectForFile(file);
@@ -715,7 +718,7 @@ module ts.server {
}
var compilerService = project.compilerService;
var position = compilerService.host.lineColToPosition(file, line, col);
var position = compilerService.host.lineOffsetToPosition(file, line, offset);
var spans = compilerService.languageService.getBraceMatchingAtPosition(file, position);
if (!spans) {
@@ -723,8 +726,8 @@ module ts.server {
}
return spans.map(span => ({
start: compilerService.host.positionToLineCol(file, span.start),
end: compilerService.host.positionToLineCol(file, span.start + span.length)
start: compilerService.host.positionToLineOffset(file, span.start),
end: compilerService.host.positionToLineOffset(file, span.start + span.length)
}));
}
@@ -741,49 +744,50 @@ module ts.server {
switch (request.command) {
case CommandNames.Definition: {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getDefinition(defArgs.line, defArgs.col, defArgs.file);
response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file);
break;
}
case CommandNames.References: {
var refArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getReferences(refArgs.line, refArgs.col, refArgs.file);
response = this.getReferences(refArgs.line, refArgs.offset, refArgs.file);
break;
}
case CommandNames.Rename: {
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
response = this.getRenameLocations(renameArgs.line, renameArgs.col, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings);
response = this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings);
break;
}
case CommandNames.Open: {
var openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file,openArgs.tabSize);
this.openClientFile(openArgs.file,openArgs.tabSize, openArgs.indentSize);
responseRequired = false;
break;
}
case CommandNames.Quickinfo: {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.col, quickinfoArgs.file);
response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file);
break;
}
case CommandNames.Format: {
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.col, formatArgs.endLine, formatArgs.endCol, formatArgs.file);
response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file);
break;
}
case CommandNames.Formatonkey: {
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.col, formatOnKeyArgs.key, formatOnKeyArgs.file);
response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file);
break;
}
case CommandNames.Completions: {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
response = this.getCompletions(request.arguments.line, request.arguments.col, completionsArgs.prefix, request.arguments.file);
response = this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file);
break;
}
case CommandNames.CompletionDetails: {
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
response = this.getCompletionEntryDetails(request.arguments.line, request.arguments.col, completionDetailsArgs.entryNames,
request.arguments.file);
response =
this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
completionDetailsArgs.entryNames,completionDetailsArgs.file);
break;
}
case CommandNames.Geterr: {
@@ -794,7 +798,7 @@ module ts.server {
}
case CommandNames.Change: {
var changeArgs = <protocol.ChangeRequestArgs>request.arguments;
this.change(changeArgs.line, changeArgs.col, changeArgs.endLine, changeArgs.endCol,
this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,
changeArgs.insertString, changeArgs.file);
responseRequired = false;
break;
@@ -831,7 +835,7 @@ module ts.server {
}
case CommandNames.Brace: {
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
response = this.getBraceMatching(braceArguments.line, braceArguments.col, braceArguments.file);
response = this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file);
break;
}
case CommandNames.NavBar: {