Skip to content

Commit dbc1522

Browse files
Merge branch 'rescript-lang:master' into css-props
2 parents c457cde + 626195e commit dbc1522

File tree

221 files changed

+3722
-3900
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

221 files changed

+3722
-3900
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ jobs:
135135
- name: Use Node.js
136136
uses: actions/setup-node@v4
137137
with:
138-
node-version: 18
138+
node-version-file: .nvmrc
139139

140140
- name: Get artifact dir name
141141
run: node .github/workflows/get_artifact_dir_name.js
@@ -167,7 +167,7 @@ jobs:
167167
key: ${{ env.opam_cache_key }}
168168

169169
- name: Use OCaml ${{matrix.ocaml_compiler}}
170-
uses: ocaml/setup-ocaml@v3.1.4
170+
uses: ocaml/setup-ocaml@v3.2.2
171171
if: steps.cache-opam-env.outputs.cache-hit != 'true'
172172
with:
173173
ocaml-compiler: ${{matrix.ocaml_compiler}}
@@ -244,11 +244,6 @@ jobs:
244244
fi
245245
shell: bash
246246

247-
# see https://github.com/ocaml/setup-ocaml/issues/815
248-
- name: "Windows: set SHELLOPTS=igncr"
249-
if: runner.os == 'Windows'
250-
run: echo "SHELLOPTS=igncr" >>"$GITHUB_ENV"
251-
252247
- name: Build compiler
253248
if: runner.os != 'Linux'
254249
run: opam exec -- dune build --display quiet --profile release
@@ -338,7 +333,7 @@ jobs:
338333
with:
339334
path: ./tests/benchmark-cache
340335
key: syntax-benchmark-v1
341-
336+
342337
- name: Create new benchmark data and comment on alert
343338
# Do not run for PRs created from other repos as those won't be able to write to the pull request
344339
if: ${{ matrix.benchmarks && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name) }}
@@ -359,7 +354,7 @@ jobs:
359354
with:
360355
path: ./tests/benchmark-cache
361356
key: syntax-benchmark-v1
362-
357+
363358
- name: Build playground compiler
364359
if: matrix.build_playground
365360
run: |
@@ -396,7 +391,7 @@ jobs:
396391
needs:
397392
- build-compiler
398393
- build-rewatch
399-
394+
400395
runs-on: ubuntu-latest
401396

402397
steps:
@@ -406,7 +401,7 @@ jobs:
406401
- name: Use Node.js
407402
uses: actions/setup-node@v4
408403
with:
409-
node-version: 18
404+
node-version-file: .nvmrc
410405

411406
- name: NPM install
412407
run: npm ci --ignore-scripts
@@ -466,7 +461,7 @@ jobs:
466461
- name: Use Node.js
467462
uses: actions/setup-node@v4
468463
with:
469-
node-version: 18
464+
node-version-file: .nvmrc
470465

471466
- name: Download artifacts
472467
uses: actions/download-artifact@v4
@@ -500,7 +495,7 @@ jobs:
500495
- name: Use Node.js
501496
uses: actions/setup-node@v4
502497
with:
503-
node-version: 18
498+
node-version-file: .nvmrc
504499
registry-url: https://registry.npmjs.org # Needed to make auth work for publishing
505500

506501
- name: Download artifacts

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18

.ocamlformat-ignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
compiler/js_parser/**
22
compiler/ml/cmt_format.ml
3-
compiler/ml/pprintast.ml
43
compiler/core/js_name_of_module_id.ml
54
compiler/core/js_pass_debug.ml
65
compiler/core/lam_util.ml

CHANGELOG.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,40 @@
1010
> - :house: [Internal]
1111
> - :nail_care: [Polish]
1212
13-
# 12.0.0-alpha.6 (Unreleased)
14-
- Fix exponential notation syntax. https://github.com/rescript-lang/rescript/pull/7174
13+
# 12.0.0-alpha.7 (Unreleased)
14+
15+
#### :house: Internal
16+
17+
- AST cleanup: use inline record for Pexp_fun. https://github.com/rescript-lang/rescript/pull/7213
18+
19+
# 12.0.0-alpha.6
20+
21+
#### :rocket: New Feature
22+
1523
- Add `Option.all` & `Result.all` helpers. https://github.com/rescript-lang/rescript/pull/7181
24+
- Add `@react.componentWithProps` for React component functions taking a props record instead of labeled arguments. https://github.com/rescript-lang/rescript/pull/7203
1625

1726
#### :bug: Bug fix
27+
28+
- Fix exponential notation syntax. https://github.com/rescript-lang/rescript/pull/7174
1829
- Fix bug where a ref assignment is moved ouside a conditional. https://github.com/rescript-lang/rescript/pull/7176
1930
- Fix nullable to opt conversion. https://github.com/rescript-lang/rescript/pull/7193
2031

2132
#### :house: Internal
33+
2234
- Use latest compiler for tests. https://github.com/rescript-lang/rescript/pull/7186
2335
- Added infra to modernise AST: theres' Parsetree, Parsetree0 (legacy), and conversion functions to keep compatibility with PPX. https://github.com/rescript-lang/rescript/pull/7185
24-
- Ast cleanup: remove exp object and exp unreachable. https://github.com/rescript-lang/rescript/pull/7189
25-
- Ast cleanup: explicit representation for optional record fields in types. https://github.com/rescript-lang/rescript/pull/7190 https://github.com/rescript-lang/rescript/pull/7191
36+
- AST cleanup: remove exp object and exp unreachable. https://github.com/rescript-lang/rescript/pull/7189
37+
- AST cleanup: explicit representation for optional record fields in types. https://github.com/rescript-lang/rescript/pull/7190 https://github.com/rescript-lang/rescript/pull/7191
2638
- AST cleanup: first-class expression and patterns for records with optional fields. https://github.com/rescript-lang/rescript/pull/7192
2739
- AST cleanup: Represent the arity of uncurried function definitions directly in the AST. https://github.com/rescript-lang/rescript/pull/7197
2840
- AST cleanup: Remove Pexp_function from the AST. https://github.com/rescript-lang/rescript/pull/7198
2941
- Remove unused code from Location and Rescript_cpp modules. https://github.com/rescript-lang/rescript/pull/7150
3042
- Build with OCaml 5.2.1. https://github.com/rescript-lang/rescript-compiler/pull/7201
43+
- AST cleanup: Remove `Function$` entirely for function definitions. https://github.com/rescript-lang/rescript/pull/7200
44+
- AST cleanup: store arity in function type. https://github.com/rescript-lang/rescript/pull/7195
45+
- AST cleanup: remove explicit uses of `function$` in preparation for removing the type entirely. https://github.com/rescript-lang/rescript/pull/7206
46+
- AST cleanup: remove `function$` entirely. https://github.com/rescript-lang/rescript/pull/7208
3147

3248
# 12.0.0-alpha.5
3349

CONTRIBUTING.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,7 @@ This is usually the file you want to create to test certain compile behavior wit
214214

215215
The "Playground bundle" is a JS version of the ReScript compiler; including all necessary dependency files (stdlib / belt etc). It is useful for building tools where you want to compile and execute arbitrary ReScript code in the browser.
216216

217-
The ReScript source code is compiled with a tool called [JSOO (js_of_ocaml)](https://ocsigen.org/js_of_ocaml/4.0.0/manual/overview), which uses OCaml bytecode to compile to JavaScript and is part of the bigger OCaml ecosystem.
218-
219-
Install `jsoo` via `opam`:
220-
221-
```sh
222-
opam install js_of_ocaml.4.0.0
223-
```
217+
The ReScript source code is compiled with a tool called [JSOO (js_of_ocaml)](https://ocsigen.org/js_of_ocaml/latest/manual/overview), which uses OCaml bytecode to compile to JavaScript and is part of the bigger OCaml ecosystem.
224218

225219
### Building the Bundle
226220

README.md

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,11 @@
99
</p>
1010

1111
<p align="center">
12-
<a href="https://www.npmjs.org/package/rescript">
13-
<img src="https://img.shields.io/npm/v/rescript?color=brightgreen&label=npm%20package" alt="Current npm package version." />
14-
</a>
15-
<a href="https://github.com/rescript-lang/rescript-compiler/actions">
16-
<img src="https://github.com//rescript-lang/rescript-compiler/workflows/CI/badge.svg" alt="Current Github Actions workflow status." />
17-
</a>
18-
<a href="https://github.com/rescript-lang/rescript-compiler/blob/HEAD/LICENSE">
19-
<img src="https://img.shields.io/badge/License-LGPL%20v3-blue.svg" alt="ReScript is released under the LGPL license." />
20-
</a>
21-
<a href="https://x.com/intent/follow?screen_name=rescriptlang">
22-
<img src="https://img.shields.io/badge/X-000000?style=flat&logo=x&logoColor=white" alt="Follow @rescriptlang on X" />
23-
</a>
24-
<a href="https://bsky.app/profile/rescript-lang.org">
25-
<img src="https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff&style=flat" alt="Follow @rescriptlang on Bluesky" />
26-
</a>
12+
<a href="https://www.npmjs.org/package/rescript"><img src="https://img.shields.io/npm/v/rescript?color=brightgreen&label=npm%20package" alt="Current npm package version." /></a>
13+
<a href="https://github.com/rescript-lang/rescript/actions"><img src="https://github.com//rescript-lang/rescript/workflows/CI/badge.svg" alt="Current Github Actions workflow status." /></a>
14+
<a href="https://github.com/rescript-lang/rescript/blob/HEAD/LICENSE"><img src="https://img.shields.io/badge/License-LGPL%20v3-blue.svg" alt="ReScript is released under the LGPL license." /></a>
15+
<a href="https://x.com/intent/follow?screen_name=rescriptlang"><img src="https://img.shields.io/badge/X-000000?style=flat&logo=x&logoColor=white" alt="Follow @rescriptlang on X" /></a>
16+
<a href="https://bsky.app/profile/rescript-lang.org"><img src="https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff&style=flat" alt="Follow @rescriptlang on Bluesky" /></a>
2717
</p>
2818

2919
<h3 align="center">

analysis/README.md

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,89 @@ See main CONTRIBUTING.md's repo structure. Additionally, `examples/` is a conven
1212

1313
## Usage
1414

15-
At root:
16-
```sh
17-
./rescript-editor-analysis.exe --help
18-
19-
# or
20-
15+
```shell
2116
dune exec -- rescript-editor-analysis --help
2217
```
2318

2419
## History
2520

2621
This project is based on a fork of [Reason Language Server](https://github.com/jaredly/reason-language-server).
22+
23+
## Tests
24+
25+
### Prerequisites
26+
27+
- Ensure the compiler is built (`make build` in the repository root).
28+
- Ensure the library is built (`make lib` in the repository root).
29+
30+
### Running the Tests
31+
32+
Run `make test` in `tests/analysis_tests/tests`.
33+
34+
### Key Concept
35+
36+
The tests in the `tests/analysis_tests/tests` folder are based on the `dune exec -- rescript-editor-analysis test` command. This special subcommand processes a file and executes specific editor analysis functionality based on special syntax found in code comments.
37+
38+
Consider the following code:
39+
40+
```res
41+
let a = 5
42+
// a.
43+
// ^com
44+
```
45+
46+
After building the ReScript project (**⚠️ this is a requirement**), you can execute `dune exec -- rescript-editor-analysis test Sample.res`, and completion will be performed for the cursor position indicated by `^`. The `com` directive requests completion. To see other commands, check out the pattern match in the `test` function in [Commands.ml](./src/Commands.ml).
47+
48+
> [!WARNING]
49+
> Ensure there are no spaces in the code comments, as the commands are captured by a regular expression that expects spaces and not tabs!
50+
51+
Here’s how it works: once a command is found in a comment, a copy of the source file is created inside a temporary directory, where the line above `^com` is uncommented. The corresponding analysis functionality is then processed, typically with `~debug:true`. With debug enabled, code paths like
52+
53+
```ml
54+
if Debug.verbose () then
55+
print_endline "[complete_typed_value]--> Tfunction #other";
56+
```
57+
58+
will print to stdout. This is helpful for observing what happens during the analysis.
59+
60+
When you run `make test` (from the `tests/analysis_tests` folder), `dune exec -- rescript-editor-analysis test <file>` will be executed for each `*.res` file in `analysis/tests/src`. The stdout will be compared to the corresponding `analysis/tests/src/expected` file. If `git diff` indicates changes, `make test` will fail, as these differences might be unintentional.
61+
62+
## Testing on Your Own Projects
63+
64+
To use a local version of `rescript-editor-analysis`, the targeted project needs to be compiled with the local compiler.
65+
66+
Install your local ReScript with `npm i /path/to/your-local-rescript-repo`.
67+
Reinstall the dependencies and run `npx rescript` in your project. This ensures the project is compiled with the same compiler version that the `rescript-editor-analysis` will process.
68+
69+
## Debugging
70+
71+
It is possible to debug `analysis` via [ocamlearlybird](https://github.com/hackwaly/ocamlearlybird).
72+
73+
1. Install `opam install earlybird`.
74+
2. Install the [earlybird extension](https://marketplace.visualstudio.com/items?itemName=hackwaly.ocamlearlybird).
75+
3. Create a launch configuration (`.vscode/launch.json`):
76+
77+
```json
78+
{
79+
"version": "0.2.0",
80+
"configurations": [
81+
{
82+
"name": "Debug analysis",
83+
"type": "ocaml.earlybird",
84+
"request": "launch",
85+
"program": "${workspaceFolder}/_build/default/analysis/bin/main.bc",
86+
"stopOnEntry": true,
87+
"cwd": "/projects/your-project",
88+
"env": {
89+
"CAML_LD_LIBRARY_PATH": "${workspaceFolder}/_build/default/compiler/ext"
90+
},
91+
"arguments": [
92+
"test",
93+
"src/Main.res"
94+
]
95+
}
96+
]
97+
}
98+
```
99+
100+
The `CAML_LD_LIBRARY_PATH` environment variable is required to tell OCaml where `dllext_stubs.so` can be loaded from.

analysis/reanalyze/src/Arnold.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ module FindFunctionsCalled = struct
545545
let findCallees (expression : Typedtree.expression) =
546546
let isFunction =
547547
match expression.exp_desc with
548-
| Texp_function _ -> true
548+
| Texp_function {arity = None} -> true
549549
| _ -> false
550550
in
551551
let callees = ref StringSet.empty in

analysis/reanalyze/src/DeadOptionalArgs.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,17 @@ let addFunctionReference ~(locFrom : Location.t) ~(locTo : Location.t) =
3131
let rec hasOptionalArgs (texpr : Types.type_expr) =
3232
match texpr.desc with
3333
| _ when not (active ()) -> false
34-
| Tarrow (Optional _, _tFrom, _tTo, _) -> true
35-
| Tarrow (_, _tFrom, tTo, _) -> hasOptionalArgs tTo
34+
| Tarrow (Optional _, _tFrom, _tTo, _, _) -> true
35+
| Tarrow (_, _tFrom, tTo, _, _) -> hasOptionalArgs tTo
3636
| Tlink t -> hasOptionalArgs t
3737
| Tsubst t -> hasOptionalArgs t
3838
| _ -> false
3939

4040
let rec fromTypeExpr (texpr : Types.type_expr) =
4141
match texpr.desc with
4242
| _ when not (active ()) -> []
43-
| Tarrow (Optional s, _tFrom, tTo, _) -> s :: fromTypeExpr tTo
44-
| Tarrow (_, _tFrom, tTo, _) -> fromTypeExpr tTo
43+
| Tarrow (Optional s, _tFrom, tTo, _, _) -> s :: fromTypeExpr tTo
44+
| Tarrow (_, _tFrom, tTo, _, _) -> fromTypeExpr tTo
4545
| Tlink t -> fromTypeExpr t
4646
| Tsubst t -> fromTypeExpr t
4747
| _ -> []

analysis/src/CompletionBackEnd.ml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
898898
| [] -> tRet
899899
| (label, tArg) :: rest ->
900900
let restType = reconstructFunctionType rest tRet in
901-
{typ with desc = Tarrow (label, tArg, restType, Cok)}
901+
{typ with desc = Tarrow (label, tArg, restType, Cok, None)}
902902
in
903903
let rec processApply args labels =
904904
match (args, labels) with
@@ -1359,11 +1359,7 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens
13591359
(* Find all functions in the module that returns type t *)
13601360
let rec fnReturnsTypeT t =
13611361
match t.Types.desc with
1362-
| Tlink t1
1363-
| Tsubst t1
1364-
| Tpoly (t1, [])
1365-
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
1366-
fnReturnsTypeT t1
1362+
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> fnReturnsTypeT t1
13671363
| Tarrow _ -> (
13681364
match TypeUtils.extractFunctionType ~env ~package:full.package t with
13691365
| ( (Nolabel, {desc = Tconstr (Path.Pident {name = "t"}, _, _)}) :: _,

analysis/src/CompletionFrontEnd.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
10931093
(* Ignore list expressions, used in JSX, unit, and more *) ()
10941094
| Pexp_construct (lid, eOpt) -> (
10951095
let lidPath = flattenLidCheckDot lid in
1096-
if debug && lid.txt <> Lident "Function$" then
1096+
if debug then
10971097
Printf.printf "Pexp_construct %s:%s %s\n"
10981098
(lidPath |> String.concat "\n")
10991099
(Loc.toString lid.loc)
@@ -1318,7 +1318,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
13181318
match exprToContextPath lhs with
13191319
| Some contextPath -> setResult (Cpath (CPObj (contextPath, label)))
13201320
| None -> ())
1321-
| Pexp_fun (lbl, defaultExpOpt, pat, e, _) ->
1321+
| Pexp_fun
1322+
{arg_label = lbl; default = defaultExpOpt; lhs = pat; rhs = e} ->
13221323
let oldScope = !scope in
13231324
(match (!processingFun, !currentCtxPath) with
13241325
| None, Some ctxPath -> processingFun := Some (ctxPath, 0)

analysis/src/CompletionJsx.ml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,7 @@ let getJsxLabels ~componentPath ~findTypeOfValue ~package =
235235
in
236236
let rec getLabels (t : Types.type_expr) =
237237
match t.desc with
238-
| Tlink t1
239-
| Tsubst t1
240-
| Tpoly (t1, [])
241-
| Tconstr (Pident {name = "function$"}, [t1; _], _) ->
242-
getLabels t1
238+
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> getLabels t1
243239
| Tconstr (p, [propsType], _) when Path.name p = "React.component" -> (
244240
let rec getPropsType (t : Types.type_expr) =
245241
match t.desc with
@@ -251,15 +247,15 @@ let getJsxLabels ~componentPath ~findTypeOfValue ~package =
251247
match propsType |> getPropsType with
252248
| Some (path, typeArgs) -> getFields ~path ~typeArgs
253249
| None -> [])
254-
| Tarrow (Nolabel, {desc = Tconstr (path, typeArgs, _)}, _, _)
250+
| Tarrow (Nolabel, {desc = Tconstr (path, typeArgs, _)}, _, _, _)
255251
when Path.last path = "props" ->
256252
getFields ~path ~typeArgs
257253
| Tconstr (clPath, [{desc = Tconstr (path, typeArgs, _)}; _], _)
258254
when Path.name clPath = "React.componentLike"
259255
&& Path.last path = "props" ->
260256
(* JSX V4 external or interface *)
261257
getFields ~path ~typeArgs
262-
| Tarrow (Nolabel, typ, _, _) -> (
258+
| Tarrow (Nolabel, typ, _, _, _) -> (
263259
(* Component without the JSX PPX, like a make fn taking a hand-written
264260
type props. *)
265261
let rec digToConstr typ =

0 commit comments

Comments
 (0)