mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
Implement codefixes in tsserver
This commit is contained in:
parent
20dea29e39
commit
4f404ad92b
96
src/server/protocol.d.ts
vendored
96
src/server/protocol.d.ts
vendored
@ -203,6 +203,53 @@ declare namespace ts.server.protocol {
|
||||
position?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request for the available codefixed at a specific position.
|
||||
*/
|
||||
export interface CodeFixRequest extends Request {
|
||||
arguments: CodeFixRequestArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instances of this interface specify errorcodes on a specific location in a sourcefile.
|
||||
*/
|
||||
export interface CodeFixRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* The line number for the request (1-based).
|
||||
*/
|
||||
startLine?: number;
|
||||
|
||||
/**
|
||||
* The character offset (on the line) for the request (1-based).
|
||||
*/
|
||||
startOffset?: number;
|
||||
|
||||
/**
|
||||
* Position (can be specified instead of line/offset pair)
|
||||
*/
|
||||
startPosition?: number;
|
||||
|
||||
/**
|
||||
* The line number for the request (1-based).
|
||||
*/
|
||||
endLine?: number;
|
||||
|
||||
/**
|
||||
* The character offset (on the line) for the request (1-based).
|
||||
*/
|
||||
endOffset?: number;
|
||||
|
||||
/**
|
||||
* Position (can be specified instead of line/offset pair)
|
||||
*/
|
||||
endPosition?: number;
|
||||
|
||||
/**
|
||||
* Errorcodes we want to get the fixes for.
|
||||
*/
|
||||
errorCodes?: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* A request whose arguments specify a file location (file, line, col).
|
||||
*/
|
||||
@ -428,7 +475,6 @@ declare namespace ts.server.protocol {
|
||||
findInStrings?: boolean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rename request; value of command field is "rename". Return
|
||||
* response giving the file locations that reference the symbol
|
||||
@ -873,6 +919,18 @@ declare namespace ts.server.protocol {
|
||||
newText: string;
|
||||
}
|
||||
|
||||
export interface FileCodeEdits {
|
||||
fileName: string;
|
||||
textChanges: CodeEdit[];
|
||||
}
|
||||
|
||||
export interface CodeActionResponse extends Response {
|
||||
/** Description of the code action to display in the UI of the editor */
|
||||
description: string;
|
||||
/** Text changes to apply to each file as part of the code action */
|
||||
changes: FileCodeEdits[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and format on key response message.
|
||||
*/
|
||||
@ -1518,4 +1576,40 @@ declare namespace ts.server.protocol {
|
||||
export interface NavBarResponse extends Response {
|
||||
body?: NavigationBarItem[];
|
||||
}
|
||||
|
||||
export interface CodeAction {
|
||||
/**
|
||||
* Description of the code action to display in the UI of the editor.
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Changes to apply to each file as part of the code action.
|
||||
*/
|
||||
changes: FileTextChanges[]
|
||||
}
|
||||
|
||||
export interface FileTextChanges {
|
||||
/**
|
||||
* File to apply the change to.
|
||||
*/
|
||||
fileName: string;
|
||||
|
||||
/**
|
||||
* Changes to apply to the file.
|
||||
*/
|
||||
textChanges: TextChange[];
|
||||
}
|
||||
|
||||
export class TextChange {
|
||||
/**
|
||||
* The span for the text change.
|
||||
*/
|
||||
span: TextSpan;
|
||||
|
||||
/**
|
||||
* New text for the span, can be an empty string if we want to delete text.
|
||||
*/
|
||||
newText: string;
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +134,8 @@ namespace ts.server {
|
||||
export const NameOrDottedNameSpan = "nameOrDottedNameSpan";
|
||||
export const BreakpointStatement = "breakpointStatement";
|
||||
export const CompilerOptionsForInferredProjects = "compilerOptionsForInferredProjects";
|
||||
export const GetCodeFixes = "getCodeFixes";
|
||||
export const GetCodeFixesFull = "getCodeFixes-full";
|
||||
}
|
||||
|
||||
export function formatMessage<T extends protocol.Message>(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string {
|
||||
@ -751,7 +753,7 @@ namespace ts.server {
|
||||
return this.getFileAndProjectWorker(args.file, args.projectFileName, /*refreshInferredProjects*/ false, errorOnMissingProject);
|
||||
}
|
||||
|
||||
private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string, refreshInferredProjects: boolean, errorOnMissingProject: boolean) {
|
||||
private getFileAndProjectWorker(uncheckedFileName: string, projectFileName: string, refreshInferredProjects: boolean, errorOnMissingProject: boolean) {
|
||||
const file = toNormalizedPath(uncheckedFileName);
|
||||
const project: Project = this.getProject(projectFileName) || this.projectService.getDefaultProjectForFile(file, refreshInferredProjects);
|
||||
if (!project && errorOnMissingProject) {
|
||||
@ -1199,6 +1201,48 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): protocol.CodeAction[] | CodeAction[] {
|
||||
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
|
||||
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||
const startPosition = getStartPosition();
|
||||
const endPosition = getEndPosition();
|
||||
|
||||
const codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes);
|
||||
if (!codeActions) {
|
||||
return undefined;
|
||||
}
|
||||
if (simplifiedResult) {
|
||||
return codeActions.map(mapCodeAction);
|
||||
} else {
|
||||
return codeActions;
|
||||
}
|
||||
|
||||
function mapCodeAction(source: CodeAction): protocol.CodeAction {
|
||||
return {
|
||||
description: source.description,
|
||||
changes: source.changes.map(change => ({
|
||||
fileName: change.fileName,
|
||||
textChanges: change.textChanges.map(textChange => ({
|
||||
span: {
|
||||
start: scriptInfo.positionToLineOffset(textChange.span.start),
|
||||
end: scriptInfo.positionToLineOffset(textChange.span.start + textChange.span.length)
|
||||
},
|
||||
newText: textChange.newText
|
||||
}))
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
function getStartPosition() {
|
||||
return args.startPosition !== undefined ? args.startPosition : scriptInfo.lineOffsetToPosition(args.startLine, args.startOffset);
|
||||
}
|
||||
|
||||
function getEndPosition() {
|
||||
return args.endPosition !== undefined ? args.endPosition : scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] {
|
||||
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
|
||||
|
||||
@ -1521,6 +1565,12 @@ namespace ts.server {
|
||||
[CommandNames.ReloadProjects]: (request: protocol.ReloadProjectsRequest) => {
|
||||
this.projectService.reloadProjects();
|
||||
return this.notRequired();
|
||||
},
|
||||
[CommandNames.GetCodeFixes]: (request: protocol.CodeFixRequest) => {
|
||||
return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.GetCodeFixesFull]: (request: protocol.CodeFixRequest) => {
|
||||
return this.requiredResponse(this.getCodeFixes(request.arguments, /*simplifiedResult*/ false));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -201,7 +201,8 @@ namespace ts.server {
|
||||
dispose: (): any => throwLanguageServiceIsDisabledError(),
|
||||
getCompletionEntrySymbol: (): any => throwLanguageServiceIsDisabledError(),
|
||||
getImplementationAtPosition: (): any => throwLanguageServiceIsDisabledError(),
|
||||
getSourceFile: (): any => throwLanguageServiceIsDisabledError()
|
||||
getSourceFile: (): any => throwLanguageServiceIsDisabledError(),
|
||||
getCodeFixesAtPosition: (): any => throwLanguageServiceIsDisabledError()
|
||||
};
|
||||
|
||||
export interface ServerLanguageServiceHost {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user