Skip to content

Commit 20fea08

Browse files
authored
Nested record definitions (#7241)
* poc of nested record definitions * tests * fix reanalyze suggestions * allow inline records in constrs * basic inline printing of nested records * update errors * output * make hovers a bit nicer * refactor away the need for res.inlineRecordReference * refactor away unecessary dot check * refactor inline types context * support type params * add tests * try disabling reanalyze * remove file * changelog * comments * remove reanalyze from ci
1 parent a99dba1 commit 20fea08

35 files changed

+796
-199
lines changed

.github/workflows/ci.yml

-10
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,6 @@ jobs:
109109
# Verify that the compiler still builds with older OCaml versions
110110
- os: ubuntu-24.04
111111
ocaml_compiler: ocaml-variants.5.2.1+options,ocaml-option-static
112-
# Reanalyze does not work on OCaml 5.3.0 anymore, therefore run it on 5.2.1
113-
run_reanalyze: true
114112
- os: ubuntu-24.04
115113
ocaml_compiler: ocaml-variants.5.0.0+options,ocaml-option-static
116114
- os: ubuntu-24.04
@@ -191,10 +189,6 @@ jobs:
191189
if: steps.cache-opam-env.outputs.cache-hit != 'true'
192190
run: opam install . --deps-only --with-test
193191

194-
- name: "Install reanalyze"
195-
if: steps.cache-opam-env.outputs.cache-hit != 'true' && matrix.run_reanalyze
196-
run: opam install reanalyze
197-
198192
- name: Cache OPAM environment
199193
if: steps.cache-opam-env.outputs.cache-hit != 'true'
200194
uses: actions/cache/save@v4
@@ -305,10 +299,6 @@ jobs:
305299
if: ${{ runner.os == 'Windows' }}
306300
run: opam exec -- make test-syntax
307301

308-
- name: "Syntax: Run reanalyze"
309-
if: matrix.run_reanalyze
310-
run: opam exec -- make reanalyze
311-
312302
- name: Build runtime/stdlib
313303
run: ./scripts/buildRuntime.sh
314304
shell: bash

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Add `inert` attribute to `JsxDOM.domProps`. https://github.com/rescript-lang/rescript/pull/7326
2020
- Make reanalyze exception tracking work with the new stdlib. https://github.com/rescript-lang/rescript/pull/7328
2121
- Fix Pervasive.max using boolean comparison for floats. https://github.com/rescript-lang/rescript/pull/7333
22+
- Experimental: Support nested/inline record types - records defined inside of other records, without needing explicit separate type definitions. https://github.com/rescript-lang/rescript/pull/7241
2223

2324
#### :boom: Breaking Change
2425

analysis/src/Hover.ml

+47-20
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,50 @@ let findRelevantTypesFromType ~file ~package typ =
101101
constructors |> List.filter_map (fromConstructorPath ~env:envToSearch)
102102

103103
let expandTypes ~file ~package ~supportsMarkdownLinks typ =
104-
findRelevantTypesFromType typ ~file ~package
105-
|> List.map (fun {decl; env; loc; path} ->
106-
let linkToTypeDefinitionStr =
107-
if supportsMarkdownLinks then
108-
Markdown.goToDefinitionText ~env ~pos:loc.Warnings.loc_start
109-
else ""
110-
in
111-
Markdown.divider
112-
^ (if supportsMarkdownLinks then Markdown.spacing else "")
113-
^ Markdown.codeBlock
114-
(decl
115-
|> Shared.declToString ~printNameAsIs:true
116-
(SharedTypes.pathIdentToString path))
117-
^ linkToTypeDefinitionStr ^ "\n")
104+
match findRelevantTypesFromType typ ~file ~package with
105+
| {decl; path} :: _
106+
when Res_parsetree_viewer.has_inline_record_definition_attribute
107+
decl.type_attributes ->
108+
(* We print inline record types just with their definition, not the constr pointing
109+
to them, since that doesn't make sense to show the user. *)
110+
( [
111+
Markdown.codeBlock
112+
(decl
113+
|> Shared.declToString ~printNameAsIs:true
114+
(SharedTypes.pathIdentToString path));
115+
],
116+
`InlineType )
117+
| all ->
118+
( all
119+
|> List.map (fun {decl; env; loc; path} ->
120+
let linkToTypeDefinitionStr =
121+
if
122+
supportsMarkdownLinks
123+
&& not
124+
(Res_parsetree_viewer
125+
.has_inline_record_definition_attribute
126+
decl.type_attributes)
127+
then Markdown.goToDefinitionText ~env ~pos:loc.Warnings.loc_start
128+
else ""
129+
in
130+
Markdown.divider
131+
^ (if supportsMarkdownLinks then Markdown.spacing else "")
132+
^ Markdown.codeBlock
133+
(decl
134+
|> Shared.declToString ~printNameAsIs:true
135+
(SharedTypes.pathIdentToString path))
136+
^ linkToTypeDefinitionStr ^ "\n"),
137+
`Default )
118138

119139
(* Produces a hover with relevant types expanded in the main type being hovered. *)
120140
let hoverWithExpandedTypes ~file ~package ~supportsMarkdownLinks typ =
121141
let typeString = Markdown.codeBlock (typ |> Shared.typeToString) in
122-
typeString :: expandTypes ~file ~package ~supportsMarkdownLinks typ
123-
|> String.concat "\n"
142+
let expandedTypes, expansionType =
143+
expandTypes ~file ~package ~supportsMarkdownLinks typ
144+
in
145+
match expansionType with
146+
| `Default -> typeString :: expandedTypes |> String.concat "\n"
147+
| `InlineType -> expandedTypes |> String.concat "\n"
124148

125149
(* Leverages autocomplete functionality to produce a hover for a position. This
126150
makes it (most often) work with unsaved content. *)
@@ -171,10 +195,13 @@ let newHover ~full:{file; package} ~supportsMarkdownLinks locItem =
171195
let typeDef = Markdown.codeBlock (Shared.declToString name decl) in
172196
match decl.type_manifest with
173197
| None -> Some typeDef
174-
| Some typ ->
175-
Some
176-
(typeDef :: expandTypes ~file ~package ~supportsMarkdownLinks typ
177-
|> String.concat "\n"))
198+
| Some typ -> (
199+
let expandedTypes, expansionType =
200+
expandTypes ~file ~package ~supportsMarkdownLinks typ
201+
in
202+
match expansionType with
203+
| `Default -> Some (typeDef :: expandedTypes |> String.concat "\n")
204+
| `InlineType -> Some (expandedTypes |> String.concat "\n")))
178205
| LModule (Definition (stamp, _tip)) | LModule (LocalReference (stamp, _tip))
179206
-> (
180207
match Stamps.findModule file.stamps stamp with

compiler/ml/ctype.ml

+2
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,7 @@ let new_declaration newtype manifest =
10161016
type_attributes = [];
10171017
type_immediate = false;
10181018
type_unboxed = unboxed_false_default_false;
1019+
type_inlined_types = [];
10191020
}
10201021

10211022
let instance_constructor ?in_pattern cstr =
@@ -4185,6 +4186,7 @@ let nondep_type_decl env mid id is_covariant decl =
41854186
type_attributes = decl.type_attributes;
41864187
type_immediate = decl.type_immediate;
41874188
type_unboxed = decl.type_unboxed;
4189+
type_inlined_types = decl.type_inlined_types;
41884190
}
41894191
with Not_found ->
41904192
clear_hash ();

compiler/ml/datarepr.ml

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ let constructor_args priv cd_args cd_res path rep =
8686
type_attributes = [];
8787
type_immediate = false;
8888
type_unboxed;
89+
type_inlined_types = [];
8990
}
9091
in
9192
(existentials, [newgenconstr path type_params], Some tdecl)

compiler/ml/predef.ml

+1
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ let decl_abstr =
203203
type_attributes = [];
204204
type_immediate = false;
205205
type_unboxed = unboxed_false_default_false;
206+
type_inlined_types = [];
206207
}
207208

208209
let decl_abstr_imm = {decl_abstr with type_immediate = true}

0 commit comments

Comments
 (0)