From 26c2d3cd52cd0a7d9f10eb73b1b918826b1a47b9 Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 19 Nov 2025 20:53:06 +0100 Subject: [PATCH 1/7] Fix hover for Stdlib module --- analysis/src/Hover.ml | 7 ++++++- tests/analysis_tests/tests/src/Hover.res | 3 +++ tests/analysis_tests/tests/src/expected/Hover.res.txt | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/analysis/src/Hover.ml b/analysis/src/Hover.ml index 716f5e3c00..05a1dcb578 100644 --- a/analysis/src/Hover.ml +++ b/analysis/src/Hover.ml @@ -275,7 +275,12 @@ let newHover ~full:{file; package} ~supportsMarkdownLinks locItem = | Some file -> showModule ~docstring:file.structure.docstring ~name:file.moduleName ~file ~package None) - | Typed (_, _, Definition (_, (Field _ | Constructor _))) -> None + | Typed (_, t, Definition (_, (Field _ | Constructor _))) -> ( + let fromType typ = + hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ + in + let t = Shared.dig t in + Some (fromType t)) | Constant t -> Some (Markdown.codeBlock diff --git a/tests/analysis_tests/tests/src/Hover.res b/tests/analysis_tests/tests/src/Hover.res index bd40d4e712..2292c216ff 100644 --- a/tests/analysis_tests/tests/src/Hover.res +++ b/tests/analysis_tests/tests/src/Hover.res @@ -281,3 +281,6 @@ module Arr = Belt.Array type aliased = variant // ^hov + +let _ = String.length("meh") +// ^hov diff --git a/tests/analysis_tests/tests/src/expected/Hover.res.txt b/tests/analysis_tests/tests/src/expected/Hover.res.txt index f9f1746e15..2c6381b7cd 100644 --- a/tests/analysis_tests/tests/src/expected/Hover.res.txt +++ b/tests/analysis_tests/tests/src/expected/Hover.res.txt @@ -348,3 +348,6 @@ Hover src/Hover.res 278:8 Hover src/Hover.res 281:6 {"contents": {"kind": "markdown", "value": "```rescript\ntype aliased = variant\n```\n\n---\n\n```\n \n```\n```rescript\ntype variant = CoolVariant | OtherCoolVariant\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C251%2C0%5D)\n"}} +Hover src/Hover.res 284:10 +{"contents": {"kind": "markdown", "value": "\n\nFunctions for interacting with JavaScript strings.\nSee: [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).\n\n---\n\n```\n \n```\n```rescript\nmodule Stdlib_String: {\n type t = string\n let make: 'a => string\n let fromCharCode: int => string\n let fromCharCodeMany: array => string\n let fromCodePoint: int => string\n let fromCodePointMany: array => string\n let equal: (string, string) => bool\n let compare: (string, string) => Ordering.t\n let length: string => int\n let get: (string, int) => option\n let getUnsafe: (string, int) => string\n let charAt: (string, int) => string\n let charCodeAt: (string, int) => option\n let charCodeAtUnsafe: (string, int) => int\n let codePointAt: (string, int) => option\n let concat: (string, string) => string\n let concatMany: (string, array) => string\n let endsWith: (string, string) => bool\n let endsWithFrom: (string, string, int) => bool\n let includes: (string, string) => bool\n let includesFrom: (string, string, int) => bool\n let indexOf: (string, string) => int\n let indexOfOpt: (string, string) => option\n let indexOfFrom: (string, string, int) => int\n let lastIndexOf: (string, string) => int\n let lastIndexOfOpt: (string, string) => option\n let lastIndexOfFrom: (string, string, int) => int\n let match: (string, RegExp.t) => option<\\\"RegExp.Result\".t>\n let normalize: string => string\n type normalizeForm = [#NFC | #NFD | #NFKC | #NFKD]\n let normalizeByForm: (string, normalizeForm) => string\n let repeat: (string, int) => string\n let replace: (string, string, string) => string\n let replaceRegExp: (string, RegExp.t, string) => string\n let replaceAll: (string, string, string) => string\n let replaceAllRegExp: (string, RegExp.t, string) => string\n let unsafeReplaceRegExpBy0: (\n string,\n RegExp.t,\n (~match: string, ~offset: int, ~input: string) => string,\n) => string\n let unsafeReplaceRegExpBy1: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let unsafeReplaceRegExpBy2: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let unsafeReplaceRegExpBy3: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~group3: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy0Unsafe: (\n string,\n RegExp.t,\n (~match: string, ~offset: int, ~input: string) => string,\n) => string\n let replaceRegExpBy1Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy2Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy3Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~group3: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let search: (string, RegExp.t) => int\n let searchOpt: (string, RegExp.t) => option\n let isEmpty: string => bool\n let capitalize: string => string\n let slice: (string, ~start: int, ~end: int=?) => string\n let sliceToEnd: (string, ~start: int) => string\n let split: (string, string) => array\n let splitAtMost: (string, string, ~limit: int) => array\n let splitByRegExp: (string, RegExp.t) => array>\n let splitByRegExpAtMost: (string, RegExp.t, ~limit: int) => array>\n let startsWith: (string, string) => bool\n let startsWithFrom: (string, string, int) => bool\n let substring: (string, ~start: int, ~end: int=?) => string\n let substringToEnd: (string, ~start: int) => string\n let toLowerCase: string => string\n let toLocaleLowerCase: string => string\n let toUpperCase: string => string\n let toLocaleUpperCase: string => string\n let trim: string => string\n let trimStart: string => string\n let trimEnd: string => string\n let padStart: (string, int, string) => string\n let padEnd: (string, int, string) => string\n let localeCompare: (string, string) => float\n let ignore: string => unit\n let getSymbolUnsafe: (string, Symbol.t) => 'a\n}\n```"}} + From 471aa28392c674d9382a49c26c793b960da9aeff Mon Sep 17 00:00:00 2001 From: nojaf Date: Wed, 19 Nov 2025 20:56:33 +0100 Subject: [PATCH 2/7] fmt --- analysis/src/Hover.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analysis/src/Hover.ml b/analysis/src/Hover.ml index 05a1dcb578..372b5d4bcb 100644 --- a/analysis/src/Hover.ml +++ b/analysis/src/Hover.ml @@ -275,12 +275,12 @@ let newHover ~full:{file; package} ~supportsMarkdownLinks locItem = | Some file -> showModule ~docstring:file.structure.docstring ~name:file.moduleName ~file ~package None) - | Typed (_, t, Definition (_, (Field _ | Constructor _))) -> ( + | Typed (_, t, Definition (_, (Field _ | Constructor _))) -> let fromType typ = hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ in let t = Shared.dig t in - Some (fromType t)) + Some (fromType t) | Constant t -> Some (Markdown.codeBlock From d4800d44b7b2fd32f0de0c4169ae9fe635b71aa5 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 20 Nov 2025 08:45:01 +0100 Subject: [PATCH 3/7] Pass runtime via environment variable --- analysis/src/BuildSystem.ml | 43 ++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/analysis/src/BuildSystem.ml b/analysis/src/BuildSystem.ml index 69eed6990b..31e71e564a 100644 --- a/analysis/src/BuildSystem.ml +++ b/analysis/src/BuildSystem.ml @@ -5,19 +5,42 @@ let namespacedName namespace name = let ( /+ ) = Filename.concat +(* +Here is the real problem: + +For pnpm it needs to figure out + +"/Users/nojaf/Projects/test-stdlib/node_modules/.pnpm/@rescript+runtime@12.0.0-rc.4/node_modules/@rescript/runtime" +*) + let getRuntimeDir rootPath = match !Cfg.isDocGenFromCompiler with | false -> ( - let result = - ModuleResolution.resolveNodeModulePath ~startPath:rootPath - "@rescript/runtime" - in - match result with - | Some path -> Some path - | None -> - let message = "@rescript/runtime could not be found" in - Log.log message; - None) + (* First check RESCRIPT_RUNTIME environment variable, like bsc does *) + match Sys.getenv_opt "RESCRIPT_RUNTIME" with + | Some envPath -> + if Debug.verbose () then + Printf.printf "[getRuntimeDir] Using RESCRIPT_RUNTIME=%s\n" envPath; + Some envPath + | None -> ( + let result = + ModuleResolution.resolveNodeModulePath ~startPath:rootPath + "@rescript/runtime" + in + match result with + | Some path -> + if Debug.verbose () then + Printf.printf "[getRuntimeDir] Resolved via node_modules: %s\n" path; + Some path + | None -> + let message = "@rescript/runtime could not be found" in + Log.log message; + if Debug.verbose () then + Printf.printf + "[getRuntimeDir] Failed to resolve @rescript/runtime from \ + rootPath=%s\n" + rootPath; + None)) | true -> Some rootPath let getLibBs path = Files.ifExists (path /+ "lib" /+ "bs") From 161ddc1f4bb0b041161eb13da44a0c398abfe39e Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 20 Nov 2025 08:50:42 +0100 Subject: [PATCH 4/7] Revert test files --- tests/analysis_tests/tests/src/Hover.res | 3 --- tests/analysis_tests/tests/src/expected/Hover.res.txt | 3 --- 2 files changed, 6 deletions(-) diff --git a/tests/analysis_tests/tests/src/Hover.res b/tests/analysis_tests/tests/src/Hover.res index 2292c216ff..bd40d4e712 100644 --- a/tests/analysis_tests/tests/src/Hover.res +++ b/tests/analysis_tests/tests/src/Hover.res @@ -281,6 +281,3 @@ module Arr = Belt.Array type aliased = variant // ^hov - -let _ = String.length("meh") -// ^hov diff --git a/tests/analysis_tests/tests/src/expected/Hover.res.txt b/tests/analysis_tests/tests/src/expected/Hover.res.txt index 2c6381b7cd..f9f1746e15 100644 --- a/tests/analysis_tests/tests/src/expected/Hover.res.txt +++ b/tests/analysis_tests/tests/src/expected/Hover.res.txt @@ -348,6 +348,3 @@ Hover src/Hover.res 278:8 Hover src/Hover.res 281:6 {"contents": {"kind": "markdown", "value": "```rescript\ntype aliased = variant\n```\n\n---\n\n```\n \n```\n```rescript\ntype variant = CoolVariant | OtherCoolVariant\n```\nGo to: [Type definition](command:rescript-vscode.go_to_location?%5B%22Hover.res%22%2C251%2C0%5D)\n"}} -Hover src/Hover.res 284:10 -{"contents": {"kind": "markdown", "value": "\n\nFunctions for interacting with JavaScript strings.\nSee: [`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String).\n\n---\n\n```\n \n```\n```rescript\nmodule Stdlib_String: {\n type t = string\n let make: 'a => string\n let fromCharCode: int => string\n let fromCharCodeMany: array => string\n let fromCodePoint: int => string\n let fromCodePointMany: array => string\n let equal: (string, string) => bool\n let compare: (string, string) => Ordering.t\n let length: string => int\n let get: (string, int) => option\n let getUnsafe: (string, int) => string\n let charAt: (string, int) => string\n let charCodeAt: (string, int) => option\n let charCodeAtUnsafe: (string, int) => int\n let codePointAt: (string, int) => option\n let concat: (string, string) => string\n let concatMany: (string, array) => string\n let endsWith: (string, string) => bool\n let endsWithFrom: (string, string, int) => bool\n let includes: (string, string) => bool\n let includesFrom: (string, string, int) => bool\n let indexOf: (string, string) => int\n let indexOfOpt: (string, string) => option\n let indexOfFrom: (string, string, int) => int\n let lastIndexOf: (string, string) => int\n let lastIndexOfOpt: (string, string) => option\n let lastIndexOfFrom: (string, string, int) => int\n let match: (string, RegExp.t) => option<\\\"RegExp.Result\".t>\n let normalize: string => string\n type normalizeForm = [#NFC | #NFD | #NFKC | #NFKD]\n let normalizeByForm: (string, normalizeForm) => string\n let repeat: (string, int) => string\n let replace: (string, string, string) => string\n let replaceRegExp: (string, RegExp.t, string) => string\n let replaceAll: (string, string, string) => string\n let replaceAllRegExp: (string, RegExp.t, string) => string\n let unsafeReplaceRegExpBy0: (\n string,\n RegExp.t,\n (~match: string, ~offset: int, ~input: string) => string,\n) => string\n let unsafeReplaceRegExpBy1: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let unsafeReplaceRegExpBy2: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let unsafeReplaceRegExpBy3: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~group3: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy0Unsafe: (\n string,\n RegExp.t,\n (~match: string, ~offset: int, ~input: string) => string,\n) => string\n let replaceRegExpBy1Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy2Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let replaceRegExpBy3Unsafe: (\n string,\n RegExp.t,\n (\n ~match: string,\n ~group1: string,\n ~group2: string,\n ~group3: string,\n ~offset: int,\n ~input: string,\n ) => string,\n) => string\n let search: (string, RegExp.t) => int\n let searchOpt: (string, RegExp.t) => option\n let isEmpty: string => bool\n let capitalize: string => string\n let slice: (string, ~start: int, ~end: int=?) => string\n let sliceToEnd: (string, ~start: int) => string\n let split: (string, string) => array\n let splitAtMost: (string, string, ~limit: int) => array\n let splitByRegExp: (string, RegExp.t) => array>\n let splitByRegExpAtMost: (string, RegExp.t, ~limit: int) => array>\n let startsWith: (string, string) => bool\n let startsWithFrom: (string, string, int) => bool\n let substring: (string, ~start: int, ~end: int=?) => string\n let substringToEnd: (string, ~start: int) => string\n let toLowerCase: string => string\n let toLocaleLowerCase: string => string\n let toUpperCase: string => string\n let toLocaleUpperCase: string => string\n let trim: string => string\n let trimStart: string => string\n let trimEnd: string => string\n let padStart: (string, int, string) => string\n let padEnd: (string, int, string) => string\n let localeCompare: (string, string) => float\n let ignore: string => unit\n let getSymbolUnsafe: (string, Symbol.t) => 'a\n}\n```"}} - From a967931be479af64ec35d7c88bca7a571debf106 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 20 Nov 2025 08:53:21 +0100 Subject: [PATCH 5/7] Add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f81e5264..f6b1e55d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ #### :house: Internal +- Editor: resolve @rescript/runtime via environment variable RESCRIPT_RUNTIME. https://github.com/rescript-lang/rescript/pull/8023 + # 12.0.0-rc.4 #### :boom: Breaking Change From ec5edd5b066c45bcc2b881edbae1976baa073ac6 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 20 Nov 2025 08:55:20 +0100 Subject: [PATCH 6/7] Revert Hover.ml --- analysis/src/Hover.ml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/analysis/src/Hover.ml b/analysis/src/Hover.ml index 372b5d4bcb..716f5e3c00 100644 --- a/analysis/src/Hover.ml +++ b/analysis/src/Hover.ml @@ -275,12 +275,7 @@ let newHover ~full:{file; package} ~supportsMarkdownLinks locItem = | Some file -> showModule ~docstring:file.structure.docstring ~name:file.moduleName ~file ~package None) - | Typed (_, t, Definition (_, (Field _ | Constructor _))) -> - let fromType typ = - hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ - in - let t = Shared.dig t in - Some (fromType t) + | Typed (_, _, Definition (_, (Field _ | Constructor _))) -> None | Constant t -> Some (Markdown.codeBlock From 417964778a048bb5dd1346c827cb75cae9f62b45 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 20 Nov 2025 11:13:58 +0100 Subject: [PATCH 7/7] Improve comment --- analysis/src/BuildSystem.ml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/analysis/src/BuildSystem.ml b/analysis/src/BuildSystem.ml index 31e71e564a..de8f9c9bbe 100644 --- a/analysis/src/BuildSystem.ml +++ b/analysis/src/BuildSystem.ml @@ -6,11 +6,8 @@ let namespacedName namespace name = let ( /+ ) = Filename.concat (* -Here is the real problem: - -For pnpm it needs to figure out - -"/Users/nojaf/Projects/test-stdlib/node_modules/.pnpm/@rescript+runtime@12.0.0-rc.4/node_modules/@rescript/runtime" +Editor tooling can more accurately resolve the runtime path and will try and pass it via an environment variable. +Example path: "test-stdlib/node_modules/.pnpm/@rescript+runtime@12.0.0-rc.4/node_modules/@rescript/runtime" *) let getRuntimeDir rootPath =