Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
912e189
Bump codecov/codecov-action from 5 to 6 (#8437)
dependabot[bot] May 28, 2026
0782ee3
Upload PR dev-playground bundles (#8447)
fhammerschmidt May 28, 2026
166253d
Use Yojson and lsp types for analysis JSON output (#8436)
aspeddro May 30, 2026
f390dfc
Update lsp and yojson dependencies (#8449)
aspeddro May 31, 2026
f0636e0
analysis: fix namespace parsing after Yojson migration (#8454)
fhammerschmidt May 31, 2026
178f352
Remove dead Ctype diagnostic relays
JonoPrest May 22, 2026
2671c12
Remove unused bs_syntaxerr conflict variant
JonoPrest May 22, 2026
ffabe81
Remove unreachable typecore label diagnostics
JonoPrest May 22, 2026
1d061e8
Remove parser-blocked typecore variants
JonoPrest May 22, 2026
e77abe3
Remove parser-blocked typetexp variants
JonoPrest May 22, 2026
6f4508d
Remove unreachable typedecl variants
JonoPrest May 22, 2026
e7206b0
Remove unreachable typemod variants
JonoPrest May 22, 2026
403ae17
Remove parser-blocked frontend syntax variants
JonoPrest May 22, 2026
02fef7c
Remove parser-blocked env value-name variant
JonoPrest May 22, 2026
6a1947f
Remove leftover typecore label helper
JonoPrest May 22, 2026
d70ef8f
Remove dead warning constructors
JonoPrest May 22, 2026
bcf2d86
Format dead error cleanup
JonoPrest May 22, 2026
5590d82
Update error variant removal audit
JonoPrest May 22, 2026
a792a7c
Restore live typedecl rebind diagnostic
JonoPrest May 22, 2026
27e91e3
Restore live typecore label diagnostics
JonoPrest May 27, 2026
977bee0
Switch defensive raise sites to assert false; revert typemod/Misplace…
JonoPrest May 27, 2026
5fa4a00
Restore reachable error variants wrongly removed as dead
JonoPrest Jun 1, 2026
a3a6278
Prove Incoherent_label_order reachable; refine Type_clash rationale
JonoPrest Jun 1, 2026
6b29137
Fix Unhandled_poly_type assert comment to the real reason
JonoPrest Jun 1, 2026
d43d92a
Restore Abstract_wrong_label to its original position
JonoPrest Jun 1, 2026
839bb3d
Remove needless line-move noise from the diff
JonoPrest Jun 1, 2026
6e1be66
Shorten Type_clash definition comment
JonoPrest Jun 1, 2026
ed53dcd
Drop Incoherent_label_order raise-site comment
JonoPrest Jun 1, 2026
e243b2c
Restore changed catalog rows to their master table positions
JonoPrest Jun 1, 2026
635ad4b
Add changelog entry for dead-variant removal
JonoPrest Jun 1, 2026
890bcc0
Re-remove dead bs_syntaxerr variants (Conflict_bs_bs_this_bs_meth, Un…
JonoPrest Jun 1, 2026
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
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,20 @@ jobs:
if: matrix.build_playground
run: yarn workspace playground test

- name: Stage PR dev playground compiler bundle
if: ${{ matrix.build_playground && github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master' && github.event.pull_request.head.repo.full_name == github.repository }}
env:
PLAYGROUND_PREVIEW_ID: pr-${{ github.event.pull_request.number }}
run: yarn workspace dev-playground stage-local-bundle "$PLAYGROUND_PREVIEW_ID"

- name: "Upload artifacts: PR dev playground compiler bundle"
if: ${{ matrix.build_playground && github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master' && github.event.pull_request.head.repo.full_name == github.repository }}
uses: actions/upload-artifact@v7
with:
name: dev-playground-pr-${{ github.event.pull_request.number }}-bundle
path: packages/dev-playground/public/playground-bundles/pr-${{ github.event.pull_request.number }}
if-no-files-found: error

- name: Stage dev playground compiler bundle
if: ${{ matrix.build_playground && github.event_name == 'push' && github.ref == 'refs/heads/master' }}
run: yarn workspace dev-playground stage-master-bundle
Expand Down Expand Up @@ -457,6 +471,7 @@ jobs:
env:
VITE_DEFAULT_COMPILER_VERSION: master
VITE_COMPILER_VERSIONS: '[{"id":"master","label":"master"}]'
VITE_COMPILER_PREVIEW_ROOT: https://cdn.rescript-lang.org/dev-playground-bundles
GITHUB_PAGES_PATH: dev-playground
PLAYGROUND_BUNDLE_ID: master
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ jobs:
key: ${{ steps.coverage-build-state-key.outputs.value }}

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
files: _coverage/coverage.json
fail_ci_if_error: false
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/playground_preview_cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Playground Preview Cleanup

on:
pull_request_target:
branches: [master]
types: [closed]

jobs:
cleanup:
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ubuntu-24.04
steps:
- name: Setup Rclone
uses: cometkim/rclone-actions/setup-rclone@main

- name: Configure Rclone remote
uses: cometkim/rclone-actions/configure-remote/s3-provider@main
with:
name: rescript
provider: Cloudflare
endpoint: https://${{ vars.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
access-key-id: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
acl: private

- name: Delete preview bundle
continue-on-error: true
run: rclone purge "rescript:cdn-assets/dev-playground-bundles/pr-${{ github.event.pull_request.number }}"
60 changes: 60 additions & 0 deletions .github/workflows/playground_preview_upload.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Playground Preview Upload

on:
workflow_run:
workflows: [CI]
types: [completed]

jobs:
upload:
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.pull_requests[0].base.ref == 'master' }}
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
pull-requests: write
env:
PLAYGROUND_PREVIEW_ID: pr-${{ github.event.workflow_run.pull_requests[0].number }}
steps:
- name: Download preview bundle artifact
uses: actions/download-artifact@v8
with:
name: dev-playground-pr-${{ github.event.workflow_run.pull_requests[0].number }}-bundle
path: dev-playground-preview-bundle
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Rclone
uses: cometkim/rclone-actions/setup-rclone@main

- name: Configure Rclone remote
uses: cometkim/rclone-actions/configure-remote/s3-provider@main
with:
name: rescript
provider: Cloudflare
endpoint: https://${{ vars.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
access-key-id: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
acl: private

- name: Upload preview bundle
run: |
rclone sync \
--stats 5 \
--checkers 5000 \
--transfers 8 \
--buffer-size 128M \
--s3-no-check-bucket \
--s3-chunk-size 128M \
--s3-upload-concurrency 8 \
--fast-list \
"dev-playground-preview-bundle" \
"rescript:cdn-assets/dev-playground-bundles/${PLAYGROUND_PREVIEW_ID}/bundle"

- name: Comment playground preview URL
uses: thollander/actions-comment-pull-request@v3
with:
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
comment-tag: dev-playground-preview
message: |
Developer playground preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev-playground/?version=pr-${{ github.event.workflow_run.pull_requests[0].number }}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
- Rewatch: use a single timestamp per compile pass. https://github.com/rescript-lang/rescript/pull/8428
- Fix rewatch warning replay after early compile errors. https://github.com/rescript-lang/rescript/pull/8408
- Fix formatting of trailing comments before `=` in let bindings. https://github.com/rescript-lang/rescript/pull/8444
- Fix analysis namespace parsing after the Yojson migration. https://github.com/rescript-lang/rescript/pull/8454

#### :memo: Documentation

Expand All @@ -43,6 +44,7 @@
- Improve deprecated attribute extraction and support record form. https://github.com/rescript-lang/rescript/pull/8396
- Refactor analysis to decouple I/O from core logic. https://github.com/rescript-lang/rescript/pull/8426
- Deprecate `Stdlib_Error` and `Stdlib_Exn` modules in favor of `JsError/JsExn`. https://github.com/rescript-lang/rescript/pull/8404
- Remove vendored `Json` library and use `yojson` and `lsp` library for analysis. https://github.com/rescript-lang/rescript/pull/8436

#### :house: Internal

Expand All @@ -54,6 +56,7 @@
- Cache OPAM env, rewatch build, and instrumented dune state in the coverage workflow. https://github.com/rescript-lang/rescript/pull/8434
- Add a multi-file fixture harness (`super_errors_multi`) for cross-module errors and warnings. https://github.com/rescript-lang/rescript/pull/8433
- Catalog every named compiler error variant in `tests/ERROR_VARIANTS.md` and add fixtures for the remaining reachable ones. https://github.com/rescript-lang/rescript/pull/8446
- Remove dead and unreachable compiler error and warning variants; add fixtures for the ones found to be reachable. https://github.com/rescript-lang/rescript/pull/8459


# 13.0.0-alpha.4
Expand Down
2 changes: 2 additions & 0 deletions analysis.opam
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ depends: [
"ocaml" {>= "5.0.0"}
"cppo" {= "1.8.0"}
"odoc" {with-doc}
"lsp" {>= "1.23.0"}
"yojson" {= "3.0.0"}
]
build: [
["dune" "subst"] {dev}
Expand Down
18 changes: 9 additions & 9 deletions analysis/bin/main.ml
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,12 @@ let main () =
| _ -> raise (Failure "unsupported type")
in
let source = Files.readFile path |> Option.value ~default:"" in
let res =
Codemod.transform ~source
~pos:(int_of_string line, int_of_string col)
~debug ~typ ~hint
|> Json.escape
in
Printf.printf "\"%s\"" res
`String
(Codemod.transform ~source
~pos:(int_of_string line, int_of_string col)
~debug ~typ ~hint)
|> Yojson.Safe.pretty_to_string ~std:true
|> print_endline
| [_; "diagnosticSyntax"; path] -> Cli.diagnosticSyntax ~path
| [_; "references"; path; line; col] ->
Cli.references ~path ~pos:(int_of_string line, int_of_string col) ~debug
Expand All @@ -198,8 +197,9 @@ let main () =
~newName ~debug
| [_; "semanticTokens"; currentFile] -> Cli.semanticTokens ~path:currentFile
| [_; "createInterface"; path; cmiFile] ->
Printf.printf "\"%s\""
(Json.escape (CreateInterface.command ~path ~cmiFile))
`String (CreateInterface.command ~path ~cmiFile)
|> Yojson.Safe.pretty_to_string ~std:true
|> print_endline
| [_; "format"; path] -> Cli.format ~path
| [_; "test"; path] -> Cli.test ~path
| [_; "cmt"; rescript_json; cmt_path] -> CmtViewer.dump rescript_json cmt_path
Expand Down
15 changes: 8 additions & 7 deletions analysis/reanalyze/src/EmitJson.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ let start () =
Printf.printf "["
let finish () = Printf.printf "\n]\n"
let emitClose () = "\n}"
let jsonString text = Yojson.Safe.to_string (`String text)

let emitItem ~ppf ~name ~kind ~file ~range ~message =
let open Format in
items := !items + 1;
let startLine, startCharacter, endLine, endCharacter = range in
fprintf ppf "%s{\n" (if !items = 1 then "\n" else ",\n");
fprintf ppf " \"name\": \"%s\",\n" name;
fprintf ppf " \"kind\": \"%s\",\n" kind;
fprintf ppf " \"file\": \"%s\",\n" file;
fprintf ppf " \"name\": %s,\n" (jsonString name);
fprintf ppf " \"kind\": %s,\n" (jsonString kind);
fprintf ppf " \"file\": %s,\n" (jsonString file);
fprintf ppf " \"range\": [%d,%d,%d,%d],\n" startLine startCharacter endLine
endCharacter;
fprintf ppf " \"message\": \"%s\"" message
fprintf ppf " \"message\": %s" (jsonString message)

let locToPos (loc : Location.t) =
(loc.loc_start.pos_lnum - 1, loc.loc_start.pos_cnum - loc.loc_start.pos_bol)
Expand All @@ -24,6 +25,6 @@ let emitAnnotate ~pos ~text ~action =
let line, character = pos in
Format.asprintf
",\n\
\ \"annotate\": { \"line\": %d, \"character\": %d, \"text\": \"%s\", \
\"action\": \"%s\"}"
line character text action
\ \"annotate\": { \"line\": %d, \"character\": %d, \"text\": %s, \
\"action\": %s}"
line character (jsonString text) (jsonString action)
4 changes: 2 additions & 2 deletions analysis/reanalyze/src/Log_.ml
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,12 @@ let logIssue ~config ~(issue : Issue.t) =
let open Format in
let loc = issue.loc in
if config.DceConfig.cli.json then
let file = Json.escape loc.loc_start.pos_fname in
let file = loc.loc_start.pos_fname in
let startLine = loc.loc_start.pos_lnum - 1 in
let startCharacter = loc.loc_start.pos_cnum - loc.loc_start.pos_bol in
let endLine = loc.loc_end.pos_lnum - 1 in
let endCharacter = loc.loc_end.pos_cnum - loc.loc_start.pos_bol in
let message = Json.escape (descriptionToMessage issue.description) in
let message = descriptionToMessage issue.description in
Format.asprintf "%a%s%s"
(fun ppf () ->
EmitJson.emitItem ~ppf ~name:issue.name
Expand Down
67 changes: 36 additions & 31 deletions analysis/reanalyze/src/Paths.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
let rescriptJson = "rescript.json"

(** If `t` is an object (`Assoc), get the value associated with the given string key *)
let get key t =
match t with
| `Assoc items -> List.assoc_opt key items
| _ -> None

let readFile filename =
try
(* windows can't use open_in *)
Expand Down Expand Up @@ -33,50 +39,49 @@ let setReScriptProjectRoot = lazy (setProjectRootFromCwd ())

module Config = struct
let readSuppress conf =
match Json.get "suppress" conf with
| Some (Array elements) ->
match conf |> get "suppress" with
| Some (`List elements) ->
let names =
elements
|> List.filter_map (fun (x : Json.t) ->
|> List.filter_map (fun (x : Yojson.Safe.t) ->
match x with
| String s -> Some s
| `String s -> Some s
| _ -> None)
in
runConfig.suppress <- names @ runConfig.suppress
| _ -> ()

let readUnsuppress conf =
match Json.get "unsuppress" conf with
| Some (Array elements) ->
match conf |> get "unsuppress" with
| Some (`List elements) ->
let names =
elements
|> List.filter_map (fun (x : Json.t) ->
|> List.filter_map (fun (x : Yojson.Safe.t) ->
match x with
| String s -> Some s
| `String s -> Some s
| _ -> None)
in
runConfig.unsuppress <- names @ runConfig.unsuppress
| _ -> ()

let readAnalysis conf =
match Json.get "analysis" conf with
| Some (Array elements) ->
match conf |> get "analysis" with
| Some (`List elements) ->
elements
|> List.iter (fun (x : Json.t) ->
|> List.iter (fun (x : Yojson.Safe.t) ->
match x with
| String "all" -> RunConfig.all ()
| String "dce" -> RunConfig.dce ()
| String "exception" -> RunConfig.exception_ ()
| String "termination" -> RunConfig.termination ()
| `String "all" -> RunConfig.all ()
| `String "dce" -> RunConfig.dce ()
| `String "exception" -> RunConfig.exception_ ()
| `String "termination" -> RunConfig.termination ()
| _ -> ())
| _ ->
(* if no "analysis" specified, default to dce *)
RunConfig.dce ()

let readTransitive conf =
match Json.get "transitive" conf with
| Some True -> RunConfig.transitive true
| Some False -> RunConfig.transitive false
match conf |> get "transitive" with
| Some (`Bool bool) -> RunConfig.transitive bool
| _ -> ()

(* Read the config from rescript.json and apply it to runConfig and suppress and unsuppress *)
Expand All @@ -85,10 +90,9 @@ module Config = struct
let rescriptFile = Filename.concat runConfig.projectRoot rescriptJson in

let processText text =
match Json.parse text with
| None -> ()
match try Some (Yojson.Safe.from_string text) with _ -> None with
| Some json -> (
match Json.get "reanalyze" json with
match get "reanalyze" json with
| Some conf ->
readSuppress conf;
readUnsuppress conf;
Expand All @@ -97,6 +101,7 @@ module Config = struct
| None ->
(* if no "analysis" specified, default to dce *)
RunConfig.dce ())
| _ -> ()
in

match readFile rescriptFile with
Expand Down Expand Up @@ -145,18 +150,18 @@ let readCmtScan () =
["lib"; "bs"; ".sourcedirs.json"]
|> List.fold_left Filename.concat runConfig.bsbProjectRoot
in
let get key fn json =
Json.get key json |> Option.to_list |> List.filter_map fn
let get_fn key fn json =
get key json |> Option.to_list |> List.filter_map fn
in
let read_entry (json : Json.t) =
let build_root = json |> get "build_root" Json.string in
let read_entry (json : Yojson.Safe.t) =
let build_root = json |> get_fn "build_root" YojsonHelpers.string_opt in
let scan_dirs =
match json |> get "scan_dirs" Json.array with
| [arr] -> arr |> List.filter_map Json.string
match json |> get "scan_dirs" with
| Some (`List arr) -> arr |> List.filter_map YojsonHelpers.string_opt
| _ -> []
in
let also_scan_build_root =
match json |> get "also_scan_build_root" Json.bool with
match json |> get_fn "also_scan_build_root" YojsonHelpers.bool_opt with
| [b] -> b
| _ -> false
in
Expand All @@ -167,9 +172,9 @@ let readCmtScan () =
match readFile sourceDirsFile with
| None -> []
| Some text -> (
match Json.parse text with
match try Some (Yojson.Safe.from_string text) with _ -> None with
| None -> []
| Some json -> (
match json |> get "cmt_scan" Json.array with
| [arr] -> arr |> List.filter_map read_entry
match get "cmt_scan" json with
| Some (`List arr) -> arr |> List.filter_map read_entry
| _ -> []))
1 change: 1 addition & 0 deletions analysis/reanalyze/src/Reanalyze.ml
Original file line number Diff line number Diff line change
Expand Up @@ -776,3 +776,4 @@ module ReanalyzeServer = ReanalyzeServer
module RunConfig = RunConfig
module DceConfig = DceConfig
module Log_ = Log_
module YojsonHelpers = YojsonHelpers
Loading
Loading