Skip to content

Commit

Permalink
CodeMapper support
Browse files Browse the repository at this point in the history
  • Loading branch information
zkat committed Aug 16, 2023
1 parent 1488256 commit cce4168
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
CompilerOptionsValue,
EndOfLineState,
FileExtensionInfo,
FileTextChanges,
HighlightSpanKind,
InteractiveRefactorArguments,
MapLike,
Expand Down Expand Up @@ -173,6 +174,7 @@ export const enum CommandTypes {
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
ProvideInlayHints = "provideInlayHints",
MapCode = "mapCode",
}

/**
Expand Down Expand Up @@ -2687,6 +2689,32 @@ export interface InlayHintsResponse extends Response {
body?: InlayHintItem[];
}

export interface MapCodeRequestArgs extends FileRequestArgs {
/// The specific code to map/insert/replace in the file.
contents: string[];

/// Optional contextual information to improve mapping results based on heuristics.
context?: MapCodeContext;
}

export interface MapCodeContext {
/// The currently selected/contextual spans to use for mapping heuristics.
/// Lower-index items will be given higher priority.
selected?: TextSpan[];

/// Changes to apply to the workspace before calculating the mapped edits.
updates?: FileTextChanges[];
}

export interface MapCodeRequest extends Request {
command: CommandTypes.MapCode,
arguments: MapCodeRequestArgs;
}

export interface MapCodeResponse extends Response {
body: FileCodeEdits[]
}

/**
* Synchronous request for semantic diagnostics of one file.
*/
Expand Down
29 changes: 29 additions & 0 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1887,6 +1887,32 @@ export class Session<TMessage = string> implements EventSender {
});
}

private mapCode(args: protocol.MapCodeRequestArgs): protocol.FileCodeEdits[] {
const { file, project } = this.getFileAndProject(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
const selected = args.context?.selected?.map(span => {
const start = scriptInfo.lineOffsetToPosition(span.start.line, span.start.offset);
const end = scriptInfo.lineOffsetToPosition(span.end.line, span.end.offset);
return {
start,
length: end - start,
};
});
return project.getLanguageService().mapCode(file, args.contents, selected, args.context?.updates)?.map(change => {
return {
fileName: change.fileName,
textChanges: change.textChanges.map(({ span, newText }) => {
const newSpan = toProtocolTextSpan(span, scriptInfo);
return {
start: newSpan.start,
end: newSpan.end,
newText
};
}),
};
});
}

private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void {
this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath);
}
Expand Down Expand Up @@ -3556,6 +3582,9 @@ export class Session<TMessage = string> implements EventSender {
[protocol.CommandTypes.ProvideInlayHints]: (request: protocol.InlayHintsRequest) => {
return this.requiredResponse(this.provideInlayHints(request.arguments));
},
[protocol.CommandTypes.MapCode]: (request: protocol.MapCodeRequest) => {
return this.requiredResponse(this.mapCode(request.arguments));
},
}));

public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
Expand Down
4 changes: 4 additions & 0 deletions src/services/_namespaces/ts.MapCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* Generated file to emulate the ts.MapCode namespace. */

export * from "../mapCode";

2 changes: 2 additions & 0 deletions src/services/_namespaces/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import * as GoToDefinition from "./ts.GoToDefinition";
export { GoToDefinition };
import * as InlayHints from "./ts.InlayHints";
export { InlayHints };
import * as MapCode from "./ts.MapCode";
export { MapCode };
import * as JsDoc from "./ts.JsDoc";
export { JsDoc };
import * as NavigateTo from "./ts.NavigateTo";
Expand Down
23 changes: 23 additions & 0 deletions src/services/mapCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
FileTextChanges,
Program,
SourceFile,
textChanges,
TextSpan,
} from "./_namespaces/ts";

// useful stuff:
// textChanges.ChangeTracker - lots of methods for inserting nodes in the right place.
// textChanges.ChangeTracker.pushRaw() - to push `updates` before running our analysis.

/** @internal */
export function mapCode(
fileName: SourceFile,
program: Program,
contents: string[],
selected?: TextSpan[],
updates?: FileTextChanges[]
): FileTextChanges[] {
const checker = program.getTypeChecker();
return [];
}
8 changes: 8 additions & 0 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ import {
LinkedEditingInfo,
LiteralType,
map,
MapCode,
mapDefined,
MapLike,
mapOneOrMany,
Expand Down Expand Up @@ -3070,6 +3071,12 @@ export function createLanguageService(
return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences));
}

function mapCode(fileName: string, contents: string[], selected?: TextSpan[], updates?: FileTextChanges[]): FileTextChanges[] {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
return MapCode.mapCode(sourceFile, program, contents, selected, updates);
}

const ls: LanguageService = {
dispose,
cleanupSemanticCache,
Expand Down Expand Up @@ -3140,6 +3147,7 @@ export function createLanguageService(
uncommentSelection,
provideInlayHints,
getSupportedCodeFixes,
mapCode,
};

switch (languageServiceMode) {
Expand Down
2 changes: 2 additions & 0 deletions src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,8 @@ export interface LanguageService {

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

mapCode(fileName: string, contents: string[], selected?: TextSpan[], updates?: FileTextChanges[]): FileTextChanges[];

dispose(): void;
}

Expand Down

0 comments on commit cce4168

Please sign in to comment.