diff --git a/README.md b/README.md index b296e751a..cea4ceec9 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/analysis/reanalyze/src/Paths.ml b/analysis/reanalyze/src/Paths.ml index 8ff08a4bc..45341f104 100644 --- a/analysis/reanalyze/src/Paths.ml +++ b/analysis/reanalyze/src/Paths.ml @@ -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 (** diff --git a/analysis/reanalyze/src/Reanalyze.ml b/analysis/reanalyze/src/Reanalyze.ml index 6b7febeec..0355c9cb7 100644 --- a/analysis/reanalyze/src/Reanalyze.ml +++ b/analysis/reanalyze/src/Reanalyze.ml @@ -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", diff --git a/analysis/src/FindFiles.ml b/analysis/src/FindFiles.ml index 878d47555..fc3556e0a 100644 --- a/analysis/src/FindFiles.ml +++ b/analysis/src/FindFiles.ml @@ -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 -> diff --git a/analysis/src/Packages.ml b/analysis/src/Packages.ml index 06fb88503..ae0ea1e7a 100644 --- a/analysis/src/Packages.ml +++ b/analysis/src/Packages.ml @@ -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 diff --git a/package.json b/package.json index d291fa5cc..3b7fdc759 100644 --- a/package.json +++ b/package.json @@ -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" } ], diff --git a/server/src/constants.ts b/server/src/constants.ts index 0709089ab..8fc2a1214 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -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"; diff --git a/server/src/lookup.ts b/server/src/lookup.ts index 62c0535ec..eb618c06a 100644 --- a/server/src/lookup.ts +++ b/server/src/lookup.ts @@ -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); diff --git a/server/src/server.ts b/server/src/server.ts index 3bc5b3ec0..a96953154 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -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 = { diff --git a/server/src/utils.ts b/server/src/utils.ts index 76e8b7e24..a6adf8ec7 100644 --- a/server/src/utils.ts +++ b/server/src/utils.ts @@ -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);