Skip to content

relax requirement of files being in a ReScript project for formatting #385

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

Merged
merged 5 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## master

- Fix issue where using paths of the form `./something` would show multiple copies of the same file in vscode.
- When hovering on a field access, show the instantiated type of the field.
- Support autocomplete for objects from another module `M.x[...`.
Expand All @@ -8,6 +9,7 @@
- Report "Fatal error" when it happens in the compiler log (e.g. a make function with type annotation) and don't crash the extension.
- Fix issue in functions the form "~foo as name" where the location would only cover "ame".
- Extend the command to create an interface file, to support components and ReScript decorators used in bindings.
- Enable formatting files without needing the file to be in an actual ReScript project.
- New feature: Show Outline which was previously disabled.

## 1.2.1
Expand Down
6 changes: 6 additions & 0 deletions analysis/src/Cli.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ Options:

./rescript-editor-analysis.exe createInterface src/MyFile.res lib/bs/src/MyFile.cmi

format: print to stdout the formatted version of the provided file

./rescript-editor-analysis.exe format src/MyFile.res

test: run tests specified by special comments in file src/MyFile.res

./rescript-editor-analysis.exe test src/src/MyFile.res
Expand Down Expand Up @@ -86,6 +90,8 @@ let main () =
| [_; "createInterface"; path; cmiFile] ->
Printf.printf "\"%s\""
(Json.escape (CreateInterface.command ~path ~cmiFile))
| [_; "format"; path] ->
Printf.printf "\"%s\"" (Json.escape (Commands.format ~path))
| [_; "test"; path] -> Commands.test ~path
| args when List.mem "-h" args || List.mem "--help" args -> prerr_endline help
| _ ->
Expand Down
18 changes: 18 additions & 0 deletions analysis/src/Commands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,24 @@ let rename ~path ~line ~col ~newName =
in
print_endline result

let format ~path =
if Filename.check_suffix path ".res" then
let {Res_driver.parsetree = structure; comments; diagnostics} =
Res_driver.parsingEngine.parseImplementation ~forPrinter:true
~filename:path
in
if List.length diagnostics > 0 then ""
else
Res_printer.printImplementation !Res_cli.ResClflags.width structure
comments
else if Filename.check_suffix path ".resi" then
let {Res_driver.parsetree = signature; comments; diagnostics} =
Res_driver.parsingEngine.parseInterface ~forPrinter:true ~filename:path
in
if List.length diagnostics > 0 then ""
else Res_printer.printInterface !Res_cli.ResClflags.width signature comments
else ""

let test ~path =
Uri2.stripPath := true;
match Files.readFile path with
Expand Down
68 changes: 28 additions & 40 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,49 +463,37 @@ function format(msg: p.RequestMessage): Array<m.Message> {
// See comment on findBscNativeDirOfFile for why we need
// to recursively search for bsc.exe upward
let bscNativePath = utils.findBscNativeOfFile(filePath);
if (bscNativePath === null) {
let params: p.ShowMessageParams = {
type: p.MessageType.Error,
message: `Cannot find a nearby bsc.exe in rescript or bs-platform. It's needed for formatting.`,
};
let response: m.NotificationMessage = {

// code will always be defined here, even though technically it can be undefined
let code = getOpenedFileContent(params.textDocument.uri);
let formattedResult = utils.formatCode(
code,
bscNativePath,
extension === c.resiExt
);
if (formattedResult.kind === "success") {
let max = code.length;
let result: p.TextEdit[] = [
{
range: {
start: { line: 0, character: 0 },
end: { line: max, character: max },
},
newText: formattedResult.result,
},
];
let response: m.ResponseMessage = {
jsonrpc: c.jsonrpcVersion,
method: "window/showMessage",
params: params,
id: msg.id,
result: result,
};
return [fakeSuccessResponse, response];
return [response];
} else {
// code will always be defined here, even though technically it can be undefined
let code = getOpenedFileContent(params.textDocument.uri);
let formattedResult = utils.formatUsingValidBscNativePath(
code,
bscNativePath,
extension === c.resiExt
);
if (formattedResult.kind === "success") {
let max = code.length;
let result: p.TextEdit[] = [
{
range: {
start: { line: 0, character: 0 },
end: { line: max, character: max },
},
newText: formattedResult.result,
},
];
let response: m.ResponseMessage = {
jsonrpc: c.jsonrpcVersion,
id: msg.id,
result: result,
};
return [response];
} else {
// let the diagnostics logic display the updated syntax errors,
// from the build.
// Again, not sending the actual errors. See fakeSuccessResponse
// above for explanation
return [fakeSuccessResponse];
}
// let the diagnostics logic display the updated syntax errors,
// from the build.
// Again, not sending the actual errors. See fakeSuccessResponse
// above for explanation
return [fakeSuccessResponse];
}
}
}
Expand Down
52 changes: 39 additions & 13 deletions server/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ type execResult =
kind: "error";
error: string;
};
export let formatUsingValidBscNativePath = (
export let formatCode = (
code: string,
bscNativePath: p.DocumentUri,
bscNativePath: p.DocumentUri | null,
isInterface: boolean
): execResult => {
let extension = isInterface ? c.resiExt : c.resExt;
Expand All @@ -104,16 +104,41 @@ export let formatUsingValidBscNativePath = (
encoding: "utf-8",
});
try {
let result = childProcess.execFileSync(bscNativePath, [
"-color",
"never",
"-format",
formatTempFileFullPath,
]);
return {
kind: "success",
result: result.toString(),
};
// Default to using the project formatter. If not, use the one we ship with
// the analysis binary in the extension itself.
if (bscNativePath != null) {
let result = childProcess.execFileSync(bscNativePath, [
"-color",
"never",
"-format",
formatTempFileFullPath,
]);
return {
kind: "success",
result: result.toString(),
};
} else {
let result = runAnalysisAfterSanityCheck(
formatTempFileFullPath,
["format", formatTempFileFullPath],
false
);

// The formatter returning an empty string means it couldn't format the
// sources, probably because of errors. In that case, we bail from
// formatting by returning the unformatted content.
if (result === "") {
return {
kind: "success",
result: code,
};
}

return {
kind: "success",
result,
};
}
} catch (e) {
return {
kind: "error",
Expand All @@ -128,7 +153,7 @@ export let formatUsingValidBscNativePath = (
export let runAnalysisAfterSanityCheck = (
filePath: p.DocumentUri,
args: Array<any>,
projectRequired=false
projectRequired = false
) => {
let binaryPath;
if (fs.existsSync(c.analysisDevPath)) {
Expand All @@ -148,6 +173,7 @@ export let runAnalysisAfterSanityCheck = (
maxBuffer: Infinity,
};
let stdout = childProcess.execFileSync(binaryPath, args, options);

return JSON.parse(stdout.toString());
};

Expand Down