Move to language service

This commit is contained in:
Andrew Branch
2019-04-11 17:32:40 -07:00
parent 61425cb304
commit 0f7bc02892
10 changed files with 76 additions and 32 deletions

View File

@@ -424,6 +424,10 @@ namespace ts.server {
return renameInfo;
}
getSelectionRange() {
return notImplemented();
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] {
if (!this.lastRenameEntry ||
this.lastRenameEntry.inputs.fileName !== fileName ||

View File

@@ -472,6 +472,9 @@ namespace Harness.LanguageService {
getRenameInfo(fileName: string, position: number, options?: ts.RenameInfoOptions): ts.RenameInfo {
return unwrapJSONCallResult(this.shim.getRenameInfo(fileName, position, options));
}
getSelectionRange(fileName: string, position: number): ts.SelectionRange {
return unwrapJSONCallResult(this.shim.getSelectionRange(fileName, position));
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ts.RenameLocation[] {
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename));
}

View File

@@ -132,6 +132,8 @@ namespace ts.server.protocol {
GetEditsForFileRenameFull = "getEditsForFileRename-full",
ConfigurePlugin = "configurePlugin",
SelectionRange = "selectionRange",
/* @internal */
SelectionRangeFull = "selectionRange-full",
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
}

View File

@@ -1744,14 +1744,6 @@ namespace ts.server {
};
}
private locationsAreEqual(a: protocol.Location, b: protocol.Location): boolean {
return a.line === b.line && a.offset === b.offset;
}
private locationTextSpansAreEqual(a: protocol.TextSpan, b: protocol.TextSpan): boolean {
return this.locationsAreEqual(a.start, b.start) && this.locationsAreEqual(a.end, b.end);
}
private getNavigationTree(args: protocol.FileRequestArgs, simplifiedResult: boolean): protocol.NavigationTree | NavigationTree | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const tree = languageService.getNavigationTree(file);
@@ -2067,33 +2059,28 @@ namespace ts.server {
this.projectService.configurePlugin(args);
}
private getSelectionRange(args: protocol.SelectionRangeRequestArgs): protocol.SelectionRange[] {
private getSelectionRange(args: protocol.SelectionRangeRequestArgs, simplifiedResult: boolean) {
const { locations } = args;
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const sourceFile = languageService.getNonBoundSourceFile(file);
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(file));
return map(locations, location => {
const pos = this.getPosition(location, scriptInfo);
let selectionRange: protocol.SelectionRange | undefined;
const pushSelectionRange = (start: number, end: number, syntaxKind?: SyntaxKind): void => {
// Skip ranges that are identical to the parent
const textSpan = this.toLocationTextSpan(createTextSpanFromBounds(start, end), scriptInfo);
if (!selectionRange || !this.locationTextSpansAreEqual(textSpan, selectionRange.textSpan)) {
selectionRange = { textSpan, ...selectionRange && { parent: selectionRange } };
if (syntaxKind) {
Object.defineProperty(selectionRange, "__debugKind", { value: formatSyntaxKind(syntaxKind) });
}
}
};
getSelectionRange(pos, sourceFile, pushSelectionRange);
return selectionRange!;
const selectionRange = languageService.getSelectionRange(file, pos);
return simplifiedResult ? this.mapSelectionRange(selectionRange, scriptInfo) : selectionRange;
});
}
private mapSelectionRange(selectionRange: SelectionRange, scriptInfo: ScriptInfo): protocol.SelectionRange {
const result: protocol.SelectionRange = {
textSpan: this.toLocationTextSpan(selectionRange.textSpan, scriptInfo),
};
if (selectionRange.parent) {
result.parent = this.mapSelectionRange(selectionRange.parent, scriptInfo);
}
return result;
}
getCanonicalFileName(fileName: string) {
const name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
return normalizePath(name);
@@ -2451,8 +2438,11 @@ namespace ts.server {
return this.notRequired();
},
[CommandNames.SelectionRange]: (request: protocol.SelectionRangeRequest) => {
return this.requiredResponse(this.getSelectionRange(request.arguments));
}
return this.requiredResponse(this.getSelectionRange(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.SelectionRangeFull]: (request: protocol.SelectionRangeRequest) => {
return this.requiredResponse(this.getSelectionRange(request.arguments, /*simplifiedResult*/ false));
},
});
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {

View File

@@ -21,7 +21,6 @@
"typingsCache.ts",
"project.ts",
"editorServices.ts",
"selectionRange.ts",
"session.ts",
"scriptVersionCache.ts"
]

View File

@@ -1,9 +1,11 @@
/* @internal */
namespace ts.server {
namespace ts.SelectionRange {
const isImport = or(isImportDeclaration, isImportEqualsDeclaration);
export function getSelectionRange(pos: number, sourceFile: SourceFile, pushSelectionRange: (start: number, end: number, kind?: SyntaxKind) => void) {
pushSelectionRange(sourceFile.getFullStart(), sourceFile.getEnd(), SyntaxKind.SourceFile);
export function getSelectionRange(pos: number, sourceFile: SourceFile): ts.SelectionRange {
let selectionRange: SelectionRange = {
textSpan: createTextSpanFromBounds(sourceFile.getFullStart(), sourceFile.getEnd())
};
// Skip top-level SyntaxList
let parentNode = sourceFile.getChildAt(0);
@@ -86,8 +88,31 @@ namespace ts.server {
}
}
}
return selectionRange;
function pushSelectionRange(start: number, end: number, syntaxKind?: SyntaxKind): void {
// Skip ranges that are identical to the parent
const textSpan = createTextSpanFromBounds(start, end);
if (!selectionRange || !textSpansEqual(textSpan, selectionRange.textSpan)) {
selectionRange = { textSpan, ...selectionRange && { parent: selectionRange } };
if (syntaxKind) {
Object.defineProperty(selectionRange, "__debugKind", { value: formatSyntaxKind(syntaxKind) });
}
}
}
}
// function getSiblingExpansionRule<T extends Node>(parentNode: T): (SyntaxKind | SyntaxKind[])[] | undefined {
// switch (parentNode.kind) {
// case SyntaxKind.BindingElement: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken];
// case SyntaxKind.Parameter: return [SyntaxKind.Identifier, SyntaxKind.DotDotDotToken, SyntaxKind.QuestionToken];
// case SyntaxKind.PropertySignature: return [SyntaxKind.Identifier, SyntaxKind.QuestionToken, SyntaxKind.SyntaxList];
// case SyntaxKind.ElementAccessExpression: return [[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken]];
// case SyntaxKind.IndexedAccessType: return [[SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken]];
// }
// }
function getGroupBounds<T>(array: ArrayLike<T>, index: number, predicate: (element: T) => boolean): [number, number] {
let first = index;
let last = index;

View File

@@ -2087,6 +2087,10 @@ namespace ts {
};
}
function getSelectionRange(fileName: string, position: number): SelectionRange {
return SelectionRange.getSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
}
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions): ApplicableRefactorInfo[] {
synchronizeHostData();
const file = getValidSourceFile(fileName);
@@ -2134,6 +2138,7 @@ namespace ts {
getBreakpointStatementAtPosition,
getNavigateToItems,
getRenameInfo,
getSelectionRange,
findRenameLocations,
getNavigationBarItems,
getNavigationTree,

View File

@@ -165,6 +165,7 @@ namespace ts {
* { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
*/
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string;
getSelectionRange(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
@@ -838,6 +839,13 @@ namespace ts {
);
}
public getSelectionRange(fileName: string, position: number): string {
return this.forwardJSONCall(
`getSelectionRange('${fileName}', ${position})`,
() => this.languageService.getSelectionRange(fileName, position)
);
}
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): string {
return this.forwardJSONCall(
`findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments}, ${providePrefixAndSuffixTextForRename})`,

View File

@@ -28,6 +28,7 @@
"patternMatcher.ts",
"preProcess.ts",
"rename.ts",
"selectionRange.ts",
"signatureHelp.ts",
"sourcemaps.ts",
"suggestionDiagnostics.ts",

View File

@@ -297,6 +297,8 @@ namespace ts {
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getSelectionRange(fileName: string, position: number): SelectionRange;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
@@ -859,6 +861,11 @@ namespace ts {
isOptional: boolean;
}
export interface SelectionRange {
textSpan: TextSpan;
parent?: SelectionRange;
}
/**
* Represents a single signature to show in signature help.
* The id is used for subsequent calls into the language service to ask questions about the