Skip to content

Commit 9c378e8

Browse files
authored
Fix @genType issue with module aliases (rescript-lang#6113)
* WIP: Demonstrate @genType issue with module aliasesgi See rescript-lang#6112 * add the option to use the `@genType` annotation at the module level * Don't need wrapper to be a separate file. * Resolve module aliases in local modules. * Back to having the alias in an separate file. * Expand module aliases. when a module alias is created ```res module A = B ``` expand the definition of B (as in an include) for genType's purposes * Update CHANGELOG.md Fixes rescript-lang#6112
1 parent 2e7f5e3 commit 9c378e8

22 files changed

+182
-40
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Use best effort to determine the config when formatting a file.
3232
https://github.com/rescript-lang/rescript-compiler/pull/5968 https://github.com/rescript-lang/rescript-compiler/pull/6080 https://github.com/rescript-lang/rescript-compiler/pull/6086 https://github.com/rescript-lang/rescript-compiler/pull/6087
3333
- Customization of runtime representation of variants. This is work in progress. E.g. some restrictions on the input. See comments of the form "TODO: put restriction on the variant definitions allowed, to make sure this never happens". https://github.com/rescript-lang/rescript-compiler/pull/6095
3434
- Introduce untagged variants https://github.com/rescript-lang/rescript-compiler/pull/6103
35+
- GenType: add the option to use the `@genType` annotation at the module level, meaning that all the items in the module should be exported. https://github.com/rescript-lang/rescript-compiler/pull/6113
36+
- GenType: add support for `@genType` annotations on module definitions. https://github.com/rescript-lang/rescript-compiler/pull/6113
3537

3638
#### :boom: Breaking Change
3739

@@ -69,6 +71,7 @@ These are only breaking changes for unformatted code.
6971
- Fix parsing uncurried type starting with path https://github.com/rescript-lang/rescript-compiler/pull/6089
7072
- Fix bigInt comparison https://github.com/rescript-lang/rescript-compiler/pull/6097
7173
- Fixed a bug where the async attribute was not preserved when using the `@this` decorator in ReScript functions. This fix allows proper handling of async functions with the `@this` decorator. Issue: https://github.com/rescript-lang/rescript-compiler/issues/6100
74+
- Fix issue with GenType and module aliases https://github.com/rescript-lang/rescript-compiler/issues/6112
7275

7376
#### :nail_care: Polish
7477

jscomp/gentype/Annotation.ml

+9-2
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ let getDocString attributes =
154154
let hasAttribute checkText (attributes : Typedtree.attributes) =
155155
getAttributePayload checkText attributes <> None
156156

157-
let fromAttributes ~loc (attributes : Typedtree.attributes) =
157+
let fromAttributes ~(config : GenTypeConfig.t) ~loc
158+
(attributes : Typedtree.attributes) =
159+
let default = if config.everything then GenType else NoGenType in
158160
if hasAttribute tagIsGenTypeOpaque attributes then GenTypeOpaque
159161
else if hasAttribute (fun s -> tagIsGenType s || tagIsGenTypeAs s) attributes
160162
then (
@@ -166,7 +168,7 @@ let fromAttributes ~loc (attributes : Typedtree.attributes) =
166168
Format.fprintf ppf "Annotation payload is ignored")
167169
| _ -> ());
168170
GenType)
169-
else NoGenType
171+
else default
170172

171173
let rec moduleTypeCheckAnnotation ~checkAnnotation
172174
({mty_desc} : Typedtree.module_type) =
@@ -289,3 +291,8 @@ let importFromString importString : import =
289291
in
290292
let importPath = ImportPath.fromStringUnsafe importString in
291293
{name; importPath}
294+
295+
let updateConfigForModule ~(config : GenTypeConfig.t) attributes =
296+
if attributes |> hasAttribute tagIsGenType then
297+
{config with everything = true}
298+
else config

jscomp/gentype/Dependencies.ml

+18-7
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,30 @@ let rec fromPath1 ~config ~typeEnv (path : Path.t) =
1111
| Pident id -> (
1212
let name = id |> Ident.name in
1313
match typeEnv |> TypeEnv.lookup ~name with
14-
| None -> External name
14+
| None -> (typeEnv, External name)
1515
| Some typeEnv1 -> (
16+
let typeEnv2 =
17+
match typeEnv |> TypeEnv.getModule ~name with
18+
| Some typeEnv2 -> typeEnv2
19+
| None -> typeEnv1
20+
in
1621
match typeEnv1 |> TypeEnv.expandAliasToExternalModule ~name with
17-
| Some dep -> dep
22+
| Some dep -> (typeEnv2, dep)
1823
| None ->
1924
let resolvedName = name |> TypeEnv.addModulePath ~typeEnv:typeEnv1 in
20-
Internal resolvedName))
25+
(typeEnv2, Internal resolvedName)))
2126
| Pdot (Pident id, s, _pos) when id |> ScopedPackage.isGeneratedModule ~config
2227
->
23-
External (s |> ScopedPackage.addGeneratedModule ~generatedModule:id)
24-
| Pdot (p, s, _pos) -> Dot (p |> fromPath1 ~config ~typeEnv, s)
28+
( typeEnv,
29+
External (s |> ScopedPackage.addGeneratedModule ~generatedModule:id) )
30+
| Pdot (p, s, _pos) -> (
31+
let typeEnvFromP, dep = p |> fromPath1 ~config ~typeEnv in
32+
match typeEnvFromP |> TypeEnv.expandAliasToExternalModule ~name:s with
33+
| Some dep -> (typeEnvFromP, dep)
34+
| None -> (typeEnvFromP, Dot (dep, s)))
2535
| Papply _ ->
26-
Internal ("__Papply_unsupported_genType__" |> ResolvedName.fromString)
36+
( typeEnv,
37+
Internal ("__Papply_unsupported_genType__" |> ResolvedName.fromString) )
2738

2839
let rec isInternal dep =
2940
match dep with
@@ -32,7 +43,7 @@ let rec isInternal dep =
3243
| Dot (d, _) -> d |> isInternal
3344

3445
let fromPath ~config ~typeEnv path =
35-
let dep = path |> fromPath1 ~config ~typeEnv in
46+
let _, dep = path |> fromPath1 ~config ~typeEnv in
3647
if !Debug.typeResolution then
3748
Log_.item "fromPath path:%s typeEnv:%s %s resolved:%s\n" (path |> Path.name)
3849
(typeEnv |> TypeEnv.toString)

jscomp/gentype/GenTypeConfig.ml

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type t = {
99
mutable emitImportCurry: bool;
1010
mutable emitImportReact: bool;
1111
mutable emitTypePropDone: bool;
12+
mutable everything: bool;
1213
exportInterfaces: bool;
1314
generatedFileExtension: string option;
1415
module_: module_;
@@ -27,6 +28,7 @@ let default =
2728
emitImportCurry = false;
2829
emitImportReact = false;
2930
emitTypePropDone = false;
31+
everything = false;
3032
exportInterfaces = false;
3133
generatedFileExtension = None;
3234
module_ = ES6;
@@ -190,13 +192,15 @@ let readConfig ~getBsConfigFile ~namespace =
190192
| Some sourceItem -> Some sourceItem
191193
| _ -> default.sources
192194
in
195+
let everything = false in
193196
{
194197
bsbProjectRoot;
195198
bsDependencies;
196199
suffix;
197200
emitImportCurry = false;
198201
emitImportReact = false;
199202
emitTypePropDone = false;
203+
everything;
200204
exportInterfaces;
201205
generatedFileExtension;
202206
module_;

jscomp/gentype/TranslateCoreType.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ and translateCoreType_ ~config ~typeVarsGen
178178
|> Annotation.hasAttribute Annotation.tagIsString
179179
in
180180
let asInt =
181-
coreType.ctyp_attributes
182-
|> Annotation.hasAttribute Annotation.tagIsInt
181+
coreType.ctyp_attributes |> Annotation.hasAttribute Annotation.tagIsInt
183182
in
184183
let lastBsInt = ref (-1) in
185184
let noPayloads =

jscomp/gentype/TranslateSignature.ml

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ let translateSignatureValue ~config ~outputFileRelative ~resolver ~typeEnv
99
Log_.item "Translate Signature Value %s\n" (val_id |> Ident.name);
1010
let typeExpr = val_desc.ctyp_type in
1111
let addAnnotationsToFunction type_ = type_ in
12-
match (val_id, val_attributes |> Annotation.fromAttributes ~loc:val_loc) with
12+
match
13+
(val_id, val_attributes |> Annotation.fromAttributes ~config ~loc:val_loc)
14+
with
1315
| id, GenType ->
1416
id |> Ident.name
1517
|> Translation.translateValue ~attributes:val_attributes ~config
@@ -118,6 +120,10 @@ and translateSignatureItem ~config ~outputFileRelative ~resolver ~typeEnv
118120
let moduleItem =
119121
Runtime.newModuleItem ~name:(moduleTypeDeclaration.mtd_id |> Ident.name)
120122
in
123+
let config =
124+
moduleTypeDeclaration.mtd_attributes
125+
|> Annotation.updateConfigForModule ~config
126+
in
121127
typeEnv |> TypeEnv.updateModuleItem ~moduleItem;
122128
moduleTypeDeclaration
123129
|> translateModuleTypeDeclaration ~config ~outputFileRelative ~resolver

jscomp/gentype/TranslateSignatureFromTypes.ml

+7-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ and translateSignatureItemFromTypes ~config ~outputFileRelative ~resolver
6464
}
6565
| Types.Sig_module (id, moduleDeclaration, _) ->
6666
let moduleItem = Runtime.newModuleItem ~name:(id |> Ident.name) in
67+
let config =
68+
moduleDeclaration.md_attributes
69+
|> Annotation.updateConfigForModule ~config
70+
in
6771
typeEnv |> TypeEnv.updateModuleItem ~moduleItem;
6872
moduleDeclaration
6973
|> translateModuleDeclarationFromTypes ~config ~outputFileRelative ~resolver
@@ -73,7 +77,9 @@ and translateSignatureItemFromTypes ~config ~outputFileRelative ~resolver
7377
if !Debug.translation then Log_.item "Translate Sig Value %s\n" name;
7478
let moduleItem = Runtime.newModuleItem ~name in
7579
typeEnv |> TypeEnv.updateModuleItem ~moduleItem;
76-
if val_attributes |> Annotation.fromAttributes ~loc:val_loc = GenType then
80+
if
81+
val_attributes |> Annotation.fromAttributes ~config ~loc:val_loc = GenType
82+
then
7783
name
7884
|> Translation.translateValue ~attributes:val_attributes ~config
7985
~docString:(Annotation.getDocString val_attributes)

jscomp/gentype/TranslateStructure.ml

+35-23
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,10 @@ let translateValueBinding ~config ~outputFileRelative ~resolver ~typeEnv
9494
if !Debug.translation then Log_.item "Translate Value Binding %s\n" name;
9595
let moduleItem = Runtime.newModuleItem ~name in
9696
typeEnv |> TypeEnv.updateModuleItem ~moduleItem;
97-
if vb_attributes |> Annotation.fromAttributes ~loc:vb_pat.pat_loc = GenType
97+
if
98+
vb_attributes
99+
|> Annotation.fromAttributes ~config ~loc:vb_pat.pat_loc
100+
= GenType
98101
then
99102
id |> Ident.name
100103
|> Translation.translateValue ~attributes:vb_attributes ~config
@@ -137,15 +140,29 @@ let rec removeDuplicateValueBindings
137140
(boundInRest, structureItem :: filteredRest)
138141
| [] -> (StringSet.empty, [])
139142

140-
let rec translateModuleBinding ~config ~outputFileRelative ~resolver ~typeEnv
143+
let rec translateModuleBinding ~(config : GenTypeConfig.t) ~outputFileRelative
144+
~resolver ~typeEnv
141145
({mb_id; mb_expr; mb_attributes} : Typedtree.module_binding) : Translation.t
142146
=
143147
let name = mb_id |> Ident.name in
144148
if !Debug.translation then Log_.item "Translate Module Binding %s\n" name;
145149
let moduleItem = Runtime.newModuleItem ~name in
150+
let config = mb_attributes |> Annotation.updateConfigForModule ~config in
146151
typeEnv |> TypeEnv.updateModuleItem ~moduleItem;
147152
let typeEnv = typeEnv |> TypeEnv.newModule ~name in
148153
match mb_expr.mod_desc with
154+
| Tmod_ident (path, _) -> (
155+
let dep = path |> Dependencies.fromPath ~config ~typeEnv in
156+
let internal = dep |> Dependencies.isInternal in
157+
typeEnv |> TypeEnv.addModuleEquation ~dep ~internal;
158+
match Env.scrape_alias mb_expr.mod_env mb_expr.mod_type with
159+
| Mty_signature signature ->
160+
(* Treat module M = N as include N *)
161+
signature
162+
|> TranslateSignatureFromTypes.translateSignatureFromTypes ~config
163+
~outputFileRelative ~resolver ~typeEnv
164+
|> Translation.combine
165+
| Mty_alias _ | Mty_ident _ | Mty_functor _ -> Translation.empty)
149166
| Tmod_structure structure ->
150167
let isLetPrivate =
151168
mb_attributes |> Annotation.hasAttribute Annotation.tagIsInternLocal
@@ -193,11 +210,6 @@ let rec translateModuleBinding ~config ~outputFileRelative ~resolver ~typeEnv
193210
| Mty_alias _ ->
194211
logNotImplemented ("Mty_alias " ^ __LOC__);
195212
Translation.empty)
196-
| Tmod_ident (path, _) ->
197-
let dep = path |> Dependencies.fromPath ~config ~typeEnv in
198-
let internal = dep |> Dependencies.isInternal in
199-
typeEnv |> TypeEnv.addModuleEquation ~dep ~internal;
200-
Translation.empty
201213
| Tmod_functor _ ->
202214
logNotImplemented ("Tmod_functor " ^ __LOC__);
203215
Translation.empty
@@ -240,9 +252,9 @@ let rec translateModuleBinding ~config ~outputFileRelative ~resolver ~typeEnv
240252
Translation.empty
241253

242254
and translateStructureItem ~config ~outputFileRelative ~resolver ~typeEnv
243-
structItem : Translation.t =
255+
(structItem : Typedtree.structure_item) : Translation.t =
244256
match structItem with
245-
| {Typedtree.str_desc = Typedtree.Tstr_type (recFlag, typeDeclarations)} ->
257+
| {str_desc = Tstr_type (recFlag, typeDeclarations)} ->
246258
{
247259
importTypes = [];
248260
codeItems = [];
@@ -252,30 +264,30 @@ and translateStructureItem ~config ~outputFileRelative ~resolver ~typeEnv
252264
~outputFileRelative ~recursive:(recFlag = Recursive) ~resolver
253265
~typeEnv;
254266
}
255-
| {Typedtree.str_desc = Tstr_value (_loc, valueBindings)} ->
267+
| {str_desc = Tstr_value (_loc, valueBindings)} ->
256268
valueBindings
257269
|> List.map
258270
(translateValueBinding ~config ~outputFileRelative ~resolver ~typeEnv)
259271
|> Translation.combine
260-
| {Typedtree.str_desc = Tstr_primitive valueDescription} ->
272+
| {str_desc = Tstr_primitive valueDescription} ->
261273
(* external declaration *)
262274
valueDescription
263275
|> Translation.translatePrimitive ~config ~outputFileRelative ~resolver
264276
~typeEnv
265-
| {Typedtree.str_desc = Tstr_module moduleBinding} ->
277+
| {str_desc = Tstr_module moduleBinding} ->
266278
moduleBinding
267279
|> translateModuleBinding ~config ~outputFileRelative ~resolver ~typeEnv
268-
| {Typedtree.str_desc = Tstr_modtype moduleTypeDeclaration} ->
280+
| {str_desc = Tstr_modtype moduleTypeDeclaration} ->
269281
moduleTypeDeclaration
270282
|> TranslateSignature.translateModuleTypeDeclaration ~config
271283
~outputFileRelative ~resolver ~typeEnv
272-
| {Typedtree.str_desc = Tstr_recmodule moduleBindings} ->
284+
| {str_desc = Tstr_recmodule moduleBindings} ->
273285
moduleBindings
274286
|> List.map
275287
(translateModuleBinding ~config ~outputFileRelative ~resolver ~typeEnv)
276288
|> Translation.combine
277289
| {
278-
Typedtree.str_desc =
290+
str_desc =
279291
(* Bucklescript's encoding of bs.module: include with constraint. *)
280292
Tstr_include
281293
{
@@ -301,30 +313,30 @@ and translateStructureItem ~config ~outputFileRelative ~resolver ~typeEnv
301313
} ->
302314
structItem1
303315
|> translateStructureItem ~config ~outputFileRelative ~resolver ~typeEnv
304-
| {Typedtree.str_desc = Tstr_include {incl_type = signature}} ->
316+
| {str_desc = Tstr_include {incl_type = signature}} ->
305317
signature
306318
|> TranslateSignatureFromTypes.translateSignatureFromTypes ~config
307319
~outputFileRelative ~resolver ~typeEnv
308320
|> Translation.combine
309-
| {Typedtree.str_desc = Tstr_eval _} ->
321+
| {str_desc = Tstr_eval _} ->
310322
logNotImplemented ("Tstr_eval " ^ __LOC__);
311323
Translation.empty
312-
| {Typedtree.str_desc = Tstr_typext _} ->
324+
| {str_desc = Tstr_typext _} ->
313325
logNotImplemented ("Tstr_typext " ^ __LOC__);
314326
Translation.empty
315-
| {Typedtree.str_desc = Tstr_exception _} ->
327+
| {str_desc = Tstr_exception _} ->
316328
logNotImplemented ("Tstr_exception " ^ __LOC__);
317329
Translation.empty
318-
| {Typedtree.str_desc = Tstr_open _} ->
330+
| {str_desc = Tstr_open _} ->
319331
logNotImplemented ("Tstr_open " ^ __LOC__);
320332
Translation.empty
321-
| {Typedtree.str_desc = Tstr_class _} ->
333+
| {str_desc = Tstr_class _} ->
322334
logNotImplemented ("Tstr_class " ^ __LOC__);
323335
Translation.empty
324-
| {Typedtree.str_desc = Tstr_class_type _} ->
336+
| {str_desc = Tstr_class_type _} ->
325337
logNotImplemented ("Tstr_class_type " ^ __LOC__);
326338
Translation.empty
327-
| {Typedtree.str_desc = Tstr_attribute _} ->
339+
| {str_desc = Tstr_attribute _} ->
328340
logNotImplemented ("Tstr_attribute " ^ __LOC__);
329341
Translation.empty
330342

jscomp/gentype/TranslateTypeDeclarations.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ let renameRecordField ~attributes ~name =
5050
let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
5151
~typeAttributes ~typeEnv ~typeName ~typeVars declarationKind :
5252
CodeItem.typeDeclaration list =
53-
let annotation = typeAttributes |> Annotation.fromAttributes ~loc in
53+
let annotation = typeAttributes |> Annotation.fromAttributes ~config ~loc in
5454
let opaque =
5555
match annotation = Annotation.GenTypeOpaque with
5656
| true -> Some true

jscomp/gentype_tests/typescript-react-example/src/FirstClassModulesInterface.gen.tsx

+8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
/* eslint-disable import/first */
33

44

5+
// @ts-ignore: Implicit any on import
6+
import * as FirstClassModulesInterfaceBS__Es6Import from './FirstClassModulesInterface.bs';
7+
const FirstClassModulesInterfaceBS: any = FirstClassModulesInterfaceBS__Es6Import;
8+
59
// tslint:disable-next-line:interface-over-type-literal
610
export type record = { readonly x: number; readonly y: string };
711

812
// tslint:disable-next-line:interface-over-type-literal
913
export type firstClassModule = { readonly x: number };
14+
15+
export const MT_x: number = FirstClassModulesInterfaceBS.MT.x;
16+
17+
export const MT: { x: number } = FirstClassModulesInterfaceBS.MT

jscomp/gentype_tests/typescript-react-example/src/Hooks.res

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ let make = (~vehicle) => {
2525
</div>
2626
}
2727

28-
@genType let default = make
28+
@genType
29+
let default = make
2930

3031
module Another = {
3132
@genType @react.component

jscomp/gentype_tests/typescript-react-example/src/JSXV4.res

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
@@jsxConfig({version: 4})
22

3+
@genType
34
module CompV4 = {
4-
@genType @react.component
5+
@react.component
56
let make = (~x, ~y) => React.string(x ++ y)
67
}
78

89
@@jsxConfig({version: 3})
910

11+
@genType
1012
module CompV3 = {
11-
@genType @react.component
13+
@react.component
1214
let make = (~x, ~y) => React.string(x ++ y)
1315
}
1416

jscomp/gentype_tests/typescript-react-example/src/MyModule.bs.js

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)