Skip to content

Commit 5db93cc

Browse files
committed
CodeMapper support
1 parent 1488256 commit 5db93cc

File tree

7 files changed

+108
-0
lines changed

7 files changed

+108
-0
lines changed

src/server/protocol.ts

+27
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ export const enum CommandTypes {
173173
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
174174
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
175175
ProvideInlayHints = "provideInlayHints",
176+
MapCode = "mapCode",
176177
}
177178

178179
/**
@@ -2687,6 +2688,32 @@ export interface InlayHintsResponse extends Response {
26872688
body?: InlayHintItem[];
26882689
}
26892690

2691+
export interface MapCodeRequestArgs extends FileRequestArgs {
2692+
/// The specific code to map/insert/replace in the file.
2693+
contents: string[];
2694+
2695+
/// Optional contextual information to improve mapping results based on heuristics.
2696+
context?: MapCodeContext;
2697+
}
2698+
2699+
export interface MapCodeContext {
2700+
/// The currently selected/contextual spans to use for mapping heuristics.
2701+
/// Lower-index items will be given higher priority.
2702+
selected?: TextSpan[];
2703+
2704+
/// Changes to apply to the workspace before calculating the mapped edits.
2705+
updates?: FileCodeEdits[];
2706+
}
2707+
2708+
export interface MapCodeRequest extends Request {
2709+
command: CommandTypes.MapCode,
2710+
arguments: MapCodeRequestArgs;
2711+
}
2712+
2713+
export interface MapCodeResponse extends Response {
2714+
body: FileCodeEdits[]
2715+
}
2716+
26902717
/**
26912718
* Synchronous request for semantic diagnostics of one file.
26922719
*/

src/server/session.ts

+42
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,45 @@ export class Session<TMessage = string> implements EventSender {
18871887
});
18881888
}
18891889

1890+
private mapCode(args: protocol.MapCodeRequestArgs): protocol.FileCodeEdits[] {
1891+
const { file, project } = this.getFileAndProject(args);
1892+
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
1893+
const selected = args.context?.selected?.map(span => {
1894+
const start = scriptInfo.lineOffsetToPosition(span.start.line, span.start.offset);
1895+
const end = scriptInfo.lineOffsetToPosition(span.end.line, span.end.offset);
1896+
return {
1897+
start,
1898+
length: end - start,
1899+
};
1900+
});
1901+
const updates = args.context?.updates?.map(edit => {
1902+
return {
1903+
fileName: edit.fileName,
1904+
textChanges: edit.textChanges.map(({ start, end, newText }) => {
1905+
const newStart = scriptInfo.lineOffsetToPosition(start.line, start.offset);
1906+
const newEnd = scriptInfo.lineOffsetToPosition(end.line, end.offset);
1907+
return {
1908+
span: { start: newStart, length: newEnd - newStart },
1909+
newText,
1910+
};
1911+
}),
1912+
};
1913+
});
1914+
return project.getLanguageService().mapCode(file, args.contents, selected, updates)?.map(change => {
1915+
return {
1916+
fileName: change.fileName,
1917+
textChanges: change.textChanges.map(({ span, newText }) => {
1918+
const newSpan = toProtocolTextSpan(span, scriptInfo);
1919+
return {
1920+
start: newSpan.start,
1921+
end: newSpan.end,
1922+
newText
1923+
};
1924+
}),
1925+
};
1926+
});
1927+
}
1928+
18901929
private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void {
18911930
this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath);
18921931
}
@@ -3556,6 +3595,9 @@ export class Session<TMessage = string> implements EventSender {
35563595
[protocol.CommandTypes.ProvideInlayHints]: (request: protocol.InlayHintsRequest) => {
35573596
return this.requiredResponse(this.provideInlayHints(request.arguments));
35583597
},
3598+
[protocol.CommandTypes.MapCode]: (request: protocol.MapCodeRequest) => {
3599+
return this.requiredResponse(this.mapCode(request.arguments));
3600+
},
35593601
}));
35603602

35613603
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* Generated file to emulate the ts.MapCode namespace. */
2+
3+
export * from "../mapCode";
4+

src/services/_namespaces/ts.ts

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import * as GoToDefinition from "./ts.GoToDefinition";
3333
export { GoToDefinition };
3434
import * as InlayHints from "./ts.InlayHints";
3535
export { InlayHints };
36+
import * as MapCode from "./ts.MapCode";
37+
export { MapCode };
3638
import * as JsDoc from "./ts.JsDoc";
3739
export { JsDoc };
3840
import * as NavigateTo from "./ts.NavigateTo";

src/services/mapCode.ts

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {
2+
FileTextChanges,
3+
Program,
4+
SourceFile,
5+
textChanges,
6+
TextSpan,
7+
} from "./_namespaces/ts";
8+
9+
// useful stuff:
10+
// textChanges.ChangeTracker - lots of methods for inserting nodes in the right place.
11+
// textChanges.ChangeTracker.pushRaw() - to push `updates` before running our analysis.
12+
13+
/** @internal */
14+
export function mapCode(
15+
file: SourceFile,
16+
program: Program,
17+
contents: string[],
18+
selected?: TextSpan[],
19+
updates?: FileTextChanges[]
20+
): FileTextChanges[] {
21+
const checker = program.getTypeChecker();
22+
return [];
23+
}

src/services/services.ts

+8
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ import {
207207
LinkedEditingInfo,
208208
LiteralType,
209209
map,
210+
MapCode,
210211
mapDefined,
211212
MapLike,
212213
mapOneOrMany,
@@ -3070,6 +3071,12 @@ export function createLanguageService(
30703071
return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences));
30713072
}
30723073

3074+
function mapCode(fileName: string, contents: string[], selected?: TextSpan[], updates?: FileTextChanges[]): FileTextChanges[] {
3075+
synchronizeHostData();
3076+
const sourceFile = getValidSourceFile(fileName);
3077+
return MapCode.mapCode(sourceFile, program, contents, selected, updates);
3078+
}
3079+
30733080
const ls: LanguageService = {
30743081
dispose,
30753082
cleanupSemanticCache,
@@ -3140,6 +3147,7 @@ export function createLanguageService(
31403147
uncommentSelection,
31413148
provideInlayHints,
31423149
getSupportedCodeFixes,
3150+
mapCode,
31433151
};
31443152

31453153
switch (languageServiceMode) {

src/services/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ export interface LanguageService {
676676

677677
getSupportedCodeFixes(fileName?: string): readonly string[];
678678

679+
mapCode(fileName: string, contents: string[], selected?: TextSpan[], updates?: FileTextChanges[]): FileTextChanges[];
680+
679681
dispose(): void;
680682
}
681683

0 commit comments

Comments
 (0)