Skip to content

Commit 9217d76

Browse files
authored
Code actions from incremental checking (#948)
* code actions from incremental compilation * changelog
1 parent 80986d3 commit 9217d76

File tree

4 files changed

+57
-5
lines changed

4 files changed

+57
-5
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#### :nail_care: Polish
2020

2121
- Enhance variant constructor payload completion. https://github.com/rescript-lang/rescript-vscode/pull/946
22+
- Clean occasional dots from "insert missing fields" code action. https://github.com/rescript-lang/rescript-vscode/pull/948
23+
- Pick up code actions in incremental compilation. https://github.com/rescript-lang/rescript-vscode/pull/948
2224

2325
## 1.48.0
2426

server/src/codeActions.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import * as p from "vscode-languageserver-protocol";
55
import * as utils from "./utils";
66
import { fileURLToPath } from "url";
77

8+
export type fileCodeActions = { range: p.Range; codeAction: p.CodeAction };
9+
810
export type filesCodeActions = {
9-
[key: string]: { range: p.Range; codeAction: p.CodeAction }[];
11+
[key: string]: fileCodeActions[];
1012
};
1113

1214
interface findCodeActionsConfig {
@@ -454,7 +456,12 @@ let addUndefinedRecordFieldsV11: codeActionExtractor = ({
454456
range,
455457
}) => {
456458
if (line.startsWith("Some required record fields are missing:")) {
457-
let recordFieldNames = line
459+
let theLine = line;
460+
if (theLine.endsWith(".")) {
461+
theLine = theLine.slice(0, theLine.length - 2);
462+
}
463+
464+
let recordFieldNames = theLine
458465
.trim()
459466
.split("Some required record fields are missing: ")[1]
460467
?.split(" ");
@@ -465,6 +472,7 @@ let addUndefinedRecordFieldsV11: codeActionExtractor = ({
465472
array.slice(index + 1).forEach((line) => {
466473
if (stop) return;
467474

475+
// Remove trailing dot, split the rest of the field names
468476
recordFieldNames.push(...line.trim().split(".")[0].split(" "));
469477

470478
if (line.includes(".")) {

server/src/incrementalCompilation.ts

+39-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as cp from "node:child_process";
99
import config, { send } from "./config";
1010
import * as c from "./constants";
1111
import * as chokidar from "chokidar";
12+
import { fileCodeActions } from "./codeActions";
1213

1314
function debug() {
1415
return (
@@ -65,6 +66,8 @@ type IncrementallyCompiledFileInfo = {
6566
/** The ReScript version. */
6667
rescriptVersion: string;
6768
};
69+
/** Any code actions for this incremental file. */
70+
codeActions: Array<fileCodeActions>;
6871
};
6972

7073
const incrementallyCompiledFileInfo: Map<
@@ -368,6 +371,7 @@ function triggerIncrementalCompilationOfFile(
368371
buildNinja: null,
369372
compilation: null,
370373
killCompilationListeners: [],
374+
codeActions: [],
371375
};
372376

373377
incrementalFileCacheEntry.project.callArgs = figureOutBscArgs(
@@ -526,7 +530,30 @@ async function compileContents(
526530
}
527531
// Reset compilation status as this compilation finished
528532
entry.compilation = null;
529-
const { result } = utils.parseCompilerLogOutput(`${stderr}\n#Done()`);
533+
const { result, codeActions } = utils.parseCompilerLogOutput(
534+
`${stderr}\n#Done()`
535+
);
536+
537+
const actions = Object.values(codeActions)[0] ?? [];
538+
539+
// Code actions will point to the locally saved incremental file, so we must remap
540+
// them so the editor understand it's supposed to apply them to the unsaved doc,
541+
// not the saved "dummy" incremental file.
542+
actions.forEach((ca) => {
543+
if (
544+
ca.codeAction.edit != null &&
545+
ca.codeAction.edit.changes != null
546+
) {
547+
const change = Object.values(ca.codeAction.edit.changes)[0];
548+
549+
ca.codeAction.edit.changes = {
550+
[pathToFileURL(entry.file.sourceFilePath).toString()]: change,
551+
};
552+
}
553+
});
554+
555+
entry.codeActions = actions;
556+
530557
const res = (Object.values(result)[0] ?? [])
531558
.map((d) => ({
532559
...d,
@@ -628,3 +655,14 @@ export function handleClosedFile(filePath: string) {
628655
originalTypeFileToFilePath.delete(entry.file.originalTypeFileLocation);
629656
incrementalFilesWatcher.unwatch([entry.file.originalTypeFileLocation]);
630657
}
658+
659+
export function getCodeActionsFromIncrementalCompilation(
660+
filePath: string
661+
): Array<fileCodeActions> | null {
662+
const entry = incrementallyCompiledFileInfo.get(filePath);
663+
if (entry != null) {
664+
return entry.codeActions;
665+
}
666+
667+
return null;
668+
}

server/src/server.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -668,9 +668,13 @@ function codeAction(msg: p.RequestMessage): p.ResponseMessage {
668668
let extension = path.extname(params.textDocument.uri);
669669
let tmpname = utils.createFileInTempDir(extension);
670670

671-
// Check local code actions coming from the diagnostics.
671+
// Check local code actions coming from the diagnostics, or from incremental compilation.
672672
let localResults: v.CodeAction[] = [];
673-
codeActionsFromDiagnostics[params.textDocument.uri]?.forEach(
673+
const fromDiagnostics =
674+
codeActionsFromDiagnostics[params.textDocument.uri] ?? [];
675+
const fromIncrementalCompilation =
676+
ic.getCodeActionsFromIncrementalCompilation(filePath) ?? [];
677+
[...fromDiagnostics, ...fromIncrementalCompilation].forEach(
674678
({ range, codeAction }) => {
675679
if (utils.rangeContainsRange(range, params.range)) {
676680
localResults.push(codeAction);

0 commit comments

Comments
 (0)