Skip to content
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

Support rescript.json #828

Merged
merged 1 commit into from
Oct 11, 2023
Merged
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ The only 2 themes we don't (and can't) support, due to their lack of coloring, a
## 💡 Features

- Supports `.res`, `.resi` and `bsconfig.json`.
- Supports `.res`, `.resi`, `rescript.json` and the legacy config file `bsconfig.json`.
- Syntax highlighting.
- Formatting.
- Build diagnostics.
@@ -100,8 +100,8 @@ You'll find all ReScript specific settings under the scope `rescript.settings`.
| Setting | Description |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Prompt to Start Build | If there's no ReScript build running already in the opened project, the extension will prompt you and ask if you want to start a build automatically. You can turn off this automatic prompt via the setting `rescript.settings.askToStartBuild`. |
| ReScript Binary Path | The extension will look for the existence of a `node_modules/.bin/rescript` file and use its directory as the `binaryPath`. If it does not find it at the project root (which is where the nearest `bsconfig.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.binaryPath` |
| ReScript Platform Path | The extension will look for the existence of a `node_modules/rescript` directory and use the subdirectory corresponding to the current platform as the `platformPath`. If it does not find it at the project root (which is where the nearest `bsconfig.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.platformPath` |
| ReScript Binary Path | The extension will look for the existence of a `node_modules/.bin/rescript` file and use its directory as the `binaryPath`. If it does not find it at the project root (which is where the nearest `rescript.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.binaryPath` |
| ReScript Platform Path | The extension will look for the existence of a `node_modules/rescript` directory and use the subdirectory corresponding to the current platform as the `platformPath`. If it does not find it at the project root (which is where the nearest `rescript.json` resides), it goes up folders in the filesystem recursively until it either finds it (often the case in monorepos) or hits the top level. To override this lookup process, the path can be configured explicitly using the setting `rescript.settings.platformPath` |
| Inlay Hints (experimental) | This allows an editor to place annotations inline with text to display type hints. Enable using `rescript.settings.inlayHints.enable: true` |
| Code Lens (experimental) | This tells the editor to add code lenses to function definitions, showing its full type above the definition. Enable using `rescript.settings.codeLens: true` |
| Signature Help | This tells the editor to show signature help when you're writing function calls. Enable using `rescript.settings.signatureHelp.enabled: true` |
@@ -140,7 +140,7 @@ The Code Analyzer is a mode in the extension that runs additional code analysis
### Configuring the Code Analyzer

You'll need to configure what code analysis you want to run, and what (if any) directories you want to ignore. Configuration is done via adding `reanalyze` in `bsconfig.json`. You'll get autocomplete for what configuration options are valid. You can also read [all about configuring `reanalyze` here](https://github.com/rescript-association/reanalyze#configuration-via-bsconfigjson).
You'll need to configure what code analysis you want to run, and what (if any) directories you want to ignore. Configuration is done via adding `reanalyze` in `rescript.json`. You'll get autocomplete for what configuration options are valid. You can also read [all about configuring `reanalyze` here](https://github.com/rescript-association/reanalyze#configuration-via-bsconfigjson).

### Usage

24 changes: 17 additions & 7 deletions analysis/reanalyze/src/Paths.ml
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ open Common
module StringMap = Map_string

let bsconfig = "bsconfig.json"
let rescriptJson = "rescript.json"

let readFile filename =
try
@@ -13,13 +14,14 @@ let readFile filename =
with _ -> None

let rec findProjectRoot ~dir =
let rescriptJsonFile = Filename.concat dir rescriptJson in
let bsconfigFile = Filename.concat dir bsconfig in
if Sys.file_exists bsconfigFile then dir
if Sys.file_exists rescriptJsonFile || Sys.file_exists bsconfigFile then dir
else
let parent = dir |> Filename.dirname in
if parent = dir then (
prerr_endline
("Error: cannot find project root containing " ^ bsconfig ^ ".");
("Error: cannot find project root containing " ^ rescriptJson ^ ".");
assert false)
else findProjectRoot ~dir:parent

@@ -79,13 +81,13 @@ module Config = struct
| Some False -> RunConfig.transitive false
| _ -> ()

(* Read the config from bsconfig.json and apply it to runConfig and suppress and unsuppress *)
(* Read the config from rescript.json/bsconfig.json and apply it to runConfig and suppress and unsuppress *)
let processBsconfig () =
Lazy.force setReScriptProjectRoot;
let rescriptFile = Filename.concat runConfig.projectRoot rescriptJson in
let bsconfigFile = Filename.concat runConfig.projectRoot bsconfig in
match readFile bsconfigFile with
| None -> ()
| Some text -> (

let processText text =
match Json.parse text with
| None -> ()
| Some json -> (
@@ -97,7 +99,15 @@ module Config = struct
readTransitive conf
| None ->
(* if no "analysis" specified, default to dce *)
RunConfig.dce ()))
RunConfig.dce ())
in

match readFile rescriptFile with
| Some text -> processText text
| None -> (
match readFile bsconfigFile with
| Some text -> processText text
| None -> ())
end

(**
4 changes: 3 additions & 1 deletion analysis/reanalyze/src/Reanalyze.ml
Original file line number Diff line number Diff line change
@@ -139,7 +139,9 @@ let cli () =
"root_path Run all the analyses for all the .cmt files under the root \
path" );
("-ci", Unit (fun () -> Cli.ci := true), "Internal flag for use in CI");
("-config", Unit setConfig, "Read the analysis mode from bsconfig.json");
( "-config",
Unit setConfig,
"Read the analysis mode from rescript.json/bsconfig.json" );
("-dce", Unit (fun () -> setDCE None), "Eperimental DCE");
("-debug", Unit (fun () -> Cli.debug := true), "Print debug information");
( "-dce-cmt",
19 changes: 14 additions & 5 deletions analysis/src/FindFiles.ml
Original file line number Diff line number Diff line change
@@ -233,9 +233,10 @@ let findDependencyFiles base config =
Json.bind
(ModuleResolution.resolveNodeModulePath ~startPath:base name)
(fun path ->
let innerPath = path /+ "bsconfig.json" in
match Files.readFile innerPath with
| Some text -> (
let rescriptJsonPath = path /+ "rescript.json" in
let bsconfigJsonPath = path /+ "bsconfig.json" in

let parseText text =
match Json.parse text with
| Some inner -> (
let namespace = getNamespace inner in
@@ -259,9 +260,17 @@ let findDependencyFiles base config =
~path ~sourceDirectories ~libBs
in
Some (compiledDirectories, projectFiles))
| None -> None)
| None -> None)
| None -> None
in

match Files.readFile rescriptJsonPath with
| Some text -> parseText text
| None -> (
match Files.readFile bsconfigJsonPath with
| Some text -> parseText text
| None -> None))
in

match result with
| Some (files, directories) -> (files, directories)
| None ->
31 changes: 21 additions & 10 deletions analysis/src/Packages.ml
Original file line number Diff line number Diff line change
@@ -12,12 +12,10 @@ let makePathsForModule ~projectFilesAndPaths ~dependenciesFilesAndPaths =
pathsForModule

let newBsPackage ~rootPath =
let bsconfig = Filename.concat rootPath "bsconfig.json" in
match Files.readFile bsconfig with
| None ->
Log.log ("Unable to read " ^ bsconfig);
None
| Some raw -> (
let rescriptJson = Filename.concat rootPath "rescript.json" in
let bsconfigJson = Filename.concat rootPath "bsconfig.json" in

let parseRaw raw =
let libBs = BuildSystem.getLibBs rootPath in
match Json.parse raw with
| Some config -> (
@@ -92,7 +90,7 @@ let newBsPackage ~rootPath =
|> List.map (fun path -> path @ ["place holder"])
in
Log.log
("Opens from bsconfig: "
("Opens from ReScript config file: "
^ (opens |> List.map pathToString |> String.concat " "));
{
rootPath;
@@ -156,15 +154,28 @@ let newBsPackage ~rootPath =
});
uncurried;
})))
| None -> None)
| None -> None
in

match Files.readFile rescriptJson with
| Some raw -> parseRaw raw
| None -> (
Log.log ("Unable to read " ^ rescriptJson);
match Files.readFile bsconfigJson with
| Some raw -> parseRaw raw
| None ->
Log.log ("Unable to read " ^ bsconfigJson);
None)

let findRoot ~uri packagesByRoot =
let path = Uri.toPath uri in
let rec loop path =
if path = "/" then None
else if Hashtbl.mem packagesByRoot path then Some (`Root path)
else if Files.exists (Filename.concat path "bsconfig.json") then
Some (`Bs path)
else if
Files.exists (Filename.concat path "rescript.json")
|| Files.exists (Filename.concat path "bsconfig.json")
then Some (`Bs path)
else
let parent = Filename.dirname path in
if parent = path then (* reached root *) None else loop parent
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@
],
"jsonValidation": [
{
"fileMatch": "bsconfig.json",
"fileMatch": ["bsconfig.json", "rescript.json"],
"url": "https://raw.githubusercontent.com/rescript-lang/rescript-compiler/master/docs/docson/build-schema.json"
}
],
1 change: 1 addition & 0 deletions server/src/constants.ts
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ export let rescriptNodePartialPath = path.join(

export let bsbLock = ".bsb.lock";
export let bsconfigPartialPath = "bsconfig.json";
export let rescriptJsonPartialPath = "rescript.json";
export let compilerDirPartialPath = path.join("lib", "bs");
export let compilerLogPartialPath = path.join("lib", "bs", ".compiler.log");
export let resExt = ".res";
33 changes: 21 additions & 12 deletions server/src/lookup.ts
Original file line number Diff line number Diff line change
@@ -46,14 +46,17 @@ export const findFilePathFromProjectRoot = (
return findFilePathFromProjectRoot(parentDir, filePartialPath);
};

export const readBsConfig = (projDir: p.DocumentUri): BuildSchema | null => {
export const readConfig = (projDir: p.DocumentUri): BuildSchema | null => {
try {
let bsconfigFile = fs.readFileSync(
path.join(projDir, c.bsconfigPartialPath),
let rescriptJson = path.join(projDir, c.rescriptJsonPartialPath);
let bsconfigJson = path.join(projDir, c.bsconfigPartialPath);

let configFile = fs.readFileSync(
fs.existsSync(rescriptJson) ? rescriptJson : bsconfigJson,
{ encoding: "utf-8" }
);

let result: BuildSchema = JSON.parse(bsconfigFile);
let result: BuildSchema = JSON.parse(configFile);
return result;
} catch (e) {
return null;
@@ -108,7 +111,7 @@ export const getFilenameFromBsconfig = (
projDir: string,
partialFilePath: string
): string | null => {
let bsconfig = readBsConfig(projDir);
let bsconfig = readConfig(projDir);

if (!bsconfig) {
return null;
@@ -126,23 +129,29 @@ export const getFilenameFromRootBsconfig = (
projDir: string,
partialFilePath: string
): string | null => {
let rootBsConfigPath = findFilePathFromProjectRoot(
let rootConfigPath = findFilePathFromProjectRoot(
path.join("..", projDir),
c.bsconfigPartialPath
c.rescriptJsonPartialPath
);

if (!rootBsConfigPath) {
if (!rootConfigPath) {
rootConfigPath = findFilePathFromProjectRoot(
path.join("..", projDir),
c.bsconfigPartialPath
);
}

if (!rootConfigPath) {
return null;
}

let rootBsconfig = readBsConfig(path.dirname(rootBsConfigPath));
let rootConfig = readConfig(path.dirname(rootConfigPath));

if (!rootBsconfig) {
if (!rootConfig) {
return null;
}

let [suffix, pathFragment] =
getSuffixAndPathFragmentFromBsconfig(rootBsconfig);
let [suffix, pathFragment] = getSuffixAndPathFragmentFromBsconfig(rootConfig);

let compiledPartialPath = replaceFileExtension(partialFilePath, suffix);

5 changes: 2 additions & 3 deletions server/src/server.ts
Original file line number Diff line number Diff line change
@@ -152,7 +152,6 @@ let openCompiledFileRequest = new v.RequestType<
void
>("textDocument/openCompiled");


let getCurrentCompilerDiagnosticsForFile = (
fileUri: string
): p.Diagnostic[] => {
@@ -896,12 +895,12 @@ function createInterface(msg: p.RequestMessage): p.Message {
let resPartialPath = filePath.split(projDir)[1];

// The .cmi filename may have a namespace suffix appended.
let namespaceResult = utils.getNamespaceNameFromBsConfig(projDir);
let namespaceResult = utils.getNamespaceNameFromConfigFile(projDir);

if (namespaceResult.kind === "error") {
let params: p.ShowMessageParams = {
type: p.MessageType.Error,
message: `Error reading bsconfig file.`,
message: `Error reading ReScript config file.`,
};

let response: p.NotificationMessage = {
23 changes: 13 additions & 10 deletions server/src/utils.ts
Original file line number Diff line number Diff line change
@@ -28,7 +28,10 @@ export let findProjectRootOfFile = (
source: p.DocumentUri
): null | p.DocumentUri => {
let dir = path.dirname(source);
if (fs.existsSync(path.join(dir, c.bsconfigPartialPath))) {
if (
fs.existsSync(path.join(dir, c.rescriptJsonPartialPath)) ||
fs.existsSync(path.join(dir, c.bsconfigPartialPath))
) {
return dir;
} else {
if (dir === source) {
@@ -192,23 +195,23 @@ export const toCamelCase = (text: string): string => {
.replace(/(\s|-)+/g, "");
};

export const getNamespaceNameFromBsConfig = (
export const getNamespaceNameFromConfigFile = (
projDir: p.DocumentUri
): execResult => {
let bsconfig = lookup.readBsConfig(projDir);
let config = lookup.readConfig(projDir);
let result = "";

if (!bsconfig) {
if (!config) {
return {
kind: "error",
error: "Could not read bsconfig",
error: "Could not read ReScript config file",
};
}

if (bsconfig.namespace === true) {
result = toCamelCase(bsconfig.name);
} else if (typeof bsconfig.namespace === "string") {
result = toCamelCase(bsconfig.namespace);
if (config.namespace === true) {
result = toCamelCase(config.name);
} else if (typeof config.namespace === "string") {
result = toCamelCase(config.namespace);
}

return {
@@ -223,7 +226,7 @@ export let getCompiledFilePath = (
): execResult => {
let error: execResult = {
kind: "error",
error: "Could not read bsconfig",
error: "Could not read ReScript config file",
};
let partialFilePath = filePath.split(projDir)[1];
let compiledPath = lookup.getFilenameFromBsconfig(projDir, partialFilePath);