-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Pvb/codeaction/api #10185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pvb/codeaction/api #10185
Changes from 21 commits
94ea825
466d26f
6f4fb06
e0b73c4
124e05f
730f31f
9a26da1
f931e60
66e1c92
49b65c7
3df79d5
682f812
6e8eb1d
20dea29
4f404ad
1cc9732
cf4e300
ebcfce4
163e758
75e1b80
1e9b653
c29e9b7
77610f6
a83a2b0
a88ceb5
f310310
7c96c28
dc516c0
9b98d00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -203,6 +203,53 @@ declare namespace ts.server.protocol { | |
position?: number; | ||
} | ||
|
||
/** | ||
* Request for the available codefixed at a specific position. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
*/ | ||
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?: number[]; | ||
} | ||
|
||
/** | ||
* 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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
/** 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[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep |
||
} | ||
|
||
/** | ||
* 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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is already defined above. |
||
/** | ||
* 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[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see formatting for example. |
||
} | ||
|
||
export interface FileTextChanges { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed. |
||
/** | ||
* File to apply the change to. | ||
*/ | ||
fileName: string; | ||
|
||
/** | ||
* Changes to apply to the file. | ||
*/ | ||
textChanges: TextChange[]; | ||
} | ||
|
||
export class TextChange { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not needed. |
||
/** | ||
* 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; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,49 @@ 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 => ({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extract the common part between here and |
||
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 +1566,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)); | ||
} | ||
}); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why? add implementation here, and add a test in tests\cases\fourslash\server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done