@@ -1291,3 +1291,256 @@ let completionPathFromMaybeBuiltin path =
1291
1291
(* Route Stdlib_X to Stdlib.X for proper completions without the Stdlib_ prefix *)
1292
1292
Some (String. split_on_char '_' mainModule)
1293
1293
| _ -> None )
1294
+
1295
+ module ExpandType = struct
1296
+ type expandTypeInput =
1297
+ | TypeExpr of {
1298
+ typeExpr : Types .type_expr ;
1299
+ name : string Location .loc option ;
1300
+ env : QueryEnv .t ;
1301
+ }
1302
+ | TypeDecl of {
1303
+ typeDecl : Types .type_declaration ;
1304
+ name : string Location .loc ;
1305
+ env : QueryEnv .t ;
1306
+ }
1307
+
1308
+ type expandTypeReturn = {
1309
+ mainTypes : expandTypeInput list ;
1310
+ relatedTypes : expandTypeInput list ;
1311
+ }
1312
+
1313
+ module TypeIdSet = Set. Make (String )
1314
+
1315
+ let expandTypes (input : expandTypeInput ) ~(full : SharedTypes.full ) =
1316
+ let rootEnv = QueryEnv. fromFile full.file in
1317
+
1318
+ let expandTypeInputToKey = function
1319
+ | TypeExpr {name; env} ->
1320
+ typeId ~env
1321
+ ~name:
1322
+ (match name with
1323
+ | None -> Location. mkloc " <unknown>" Location. none
1324
+ | Some n -> n)
1325
+ | TypeDecl {name; env} -> typeId ~env ~name
1326
+ in
1327
+
1328
+ let deduplicateAndRemoveAlreadyPresent mainTypes relatedTypes =
1329
+ let mainIds = ref TypeIdSet. empty in
1330
+ let dedupedMain =
1331
+ mainTypes
1332
+ |> List. fold_left
1333
+ (fun acc item ->
1334
+ let id = expandTypeInputToKey item in
1335
+ if TypeIdSet. mem id ! mainIds then acc
1336
+ else (
1337
+ mainIds := TypeIdSet. add id ! mainIds;
1338
+ item :: acc))
1339
+ []
1340
+ |> List. rev
1341
+ in
1342
+
1343
+ let relatedIds = ref TypeIdSet. empty in
1344
+ let dedupedRelated =
1345
+ relatedTypes
1346
+ |> List. fold_left
1347
+ (fun acc item ->
1348
+ let id = expandTypeInputToKey item in
1349
+ if TypeIdSet. mem id ! mainIds || TypeIdSet. mem id ! relatedIds then
1350
+ acc
1351
+ else (
1352
+ relatedIds := TypeIdSet. add id ! relatedIds;
1353
+ item :: acc))
1354
+ []
1355
+ |> List. rev
1356
+ in
1357
+
1358
+ (dedupedMain, dedupedRelated)
1359
+ in
1360
+
1361
+ let rec followTypeAliases acc (typeExpr : Types.type_expr ) =
1362
+ match typeExpr.desc with
1363
+ | Tlink t1 | Tsubst t1 | Tpoly (t1 , [] ) -> followTypeAliases acc t1
1364
+ | Tconstr (path , typeArgs , _ ) -> (
1365
+ match
1366
+ References. digConstructor ~env: rootEnv ~package: full.package path
1367
+ with
1368
+ | Some
1369
+ ( env,
1370
+ {
1371
+ name;
1372
+ item = {decl = {type_manifest = Some t1; type_params} as decl};
1373
+ } ) ->
1374
+ let instantiated =
1375
+ instantiateType ~type Params:type_params ~type Args t1
1376
+ in
1377
+ let currentAlias = TypeDecl {typeDecl = decl; name; env} in
1378
+ followTypeAliases (currentAlias :: acc) instantiated
1379
+ | Some (env , {name; item = {decl} } ) ->
1380
+ TypeDecl {typeDecl = decl; name; env} :: acc
1381
+ | None -> acc)
1382
+ | _ -> acc
1383
+ in
1384
+
1385
+ let rec findFinalConcreteType (typeExpr : Types.type_expr ) =
1386
+ match typeExpr.desc with
1387
+ | Tlink t1 | Tsubst t1 | Tpoly (t1 , [] ) -> findFinalConcreteType t1
1388
+ | Tconstr (path , typeArgs , _ ) -> (
1389
+ match
1390
+ References. digConstructor ~env: rootEnv ~package: full.package path
1391
+ with
1392
+ | Some (_env, {item = {decl = {type_manifest = Some t1; type_params}}})
1393
+ ->
1394
+ let instantiated =
1395
+ instantiateType ~type Params:type_params ~type Args t1
1396
+ in
1397
+ findFinalConcreteType instantiated
1398
+ | _ -> typeExpr)
1399
+ | _ -> typeExpr
1400
+ in
1401
+
1402
+ let rec extractRelevantTypesFromTypeExpr ?(depth = 0 )
1403
+ (typeExpr : Types.type_expr ) =
1404
+ if depth > 1 then []
1405
+ else
1406
+ match typeExpr.desc with
1407
+ | Tlink t1 | Tsubst t1 | Tpoly (t1 , [] ) ->
1408
+ extractRelevantTypesFromTypeExpr ~depth t1
1409
+ | Tconstr (path , typeArgs , _ ) ->
1410
+ let constructorTypes =
1411
+ match
1412
+ References. digConstructor ~env: rootEnv ~package: full.package path
1413
+ with
1414
+ | Some (env , {name; item = {kind = Record fields ; decl} } ) ->
1415
+ TypeDecl {typeDecl = decl; name; env}
1416
+ ::
1417
+ (if depth = 0 then
1418
+ fields
1419
+ |> List. fold_left
1420
+ (fun acc field ->
1421
+ acc
1422
+ @ extractRelevantTypesFromTypeExpr ~depth: (depth + 1 )
1423
+ field.typ)
1424
+ []
1425
+ else [] )
1426
+ | Some (env , {name; item = {kind = Variant constructors ; decl} } ) ->
1427
+ TypeDecl {typeDecl = decl; name; env}
1428
+ ::
1429
+ (if depth = 0 then
1430
+ constructors
1431
+ |> List. fold_left
1432
+ (fun acc (constructor : Constructor.t ) ->
1433
+ match constructor.args with
1434
+ | Args args ->
1435
+ args
1436
+ |> List. fold_left
1437
+ (fun acc (argType , _ ) ->
1438
+ acc
1439
+ @ extractRelevantTypesFromTypeExpr
1440
+ ~depth: (depth + 1 ) argType)
1441
+ acc
1442
+ | InlineRecord fields ->
1443
+ fields
1444
+ |> List. fold_left
1445
+ (fun acc field ->
1446
+ acc
1447
+ @ extractRelevantTypesFromTypeExpr
1448
+ ~depth: (depth + 1 ) field.typ)
1449
+ acc)
1450
+ []
1451
+ else [] )
1452
+ | Some (_env , {item = {decl = {type_manifest = Some t1 } } } ) ->
1453
+ extractRelevantTypesFromTypeExpr ~depth t1
1454
+ | _ -> []
1455
+ in
1456
+ let typeArgTypes =
1457
+ typeArgs
1458
+ |> List. fold_left
1459
+ (fun acc typeArg ->
1460
+ acc
1461
+ @ extractRelevantTypesFromTypeExpr ~depth: (depth + 1 ) typeArg)
1462
+ []
1463
+ in
1464
+ constructorTypes @ typeArgTypes
1465
+ | Tvariant {row_fields} when depth = 0 ->
1466
+ row_fields
1467
+ |> List. fold_left
1468
+ (fun acc (_label , field ) ->
1469
+ match field with
1470
+ | Types. Rpresent (Some typeExpr ) ->
1471
+ acc
1472
+ @ extractRelevantTypesFromTypeExpr ~depth: (depth + 1 )
1473
+ typeExpr
1474
+ | Reither (_ , typeExprs , _ , _ ) ->
1475
+ typeExprs
1476
+ |> List. fold_left
1477
+ (fun acc typeExpr ->
1478
+ acc
1479
+ @ extractRelevantTypesFromTypeExpr ~depth: (depth + 1 )
1480
+ typeExpr)
1481
+ acc
1482
+ | _ -> acc)
1483
+ []
1484
+ | _ -> []
1485
+ in
1486
+
1487
+ let extractRelevantTypesFromTypeDecl (typeDecl : Types.type_declaration ) =
1488
+ match typeDecl.type_manifest with
1489
+ | Some typeExpr -> extractRelevantTypesFromTypeExpr typeExpr
1490
+ | None -> (
1491
+ match typeDecl.type_kind with
1492
+ | Type_record (label_declarations , _ ) ->
1493
+ label_declarations
1494
+ |> List. fold_left
1495
+ (fun acc (label_decl : Types.label_declaration ) ->
1496
+ acc
1497
+ @ extractRelevantTypesFromTypeExpr ~depth: 1 label_decl.ld_type)
1498
+ []
1499
+ | Type_variant constructor_declarations ->
1500
+ constructor_declarations
1501
+ |> List. fold_left
1502
+ (fun acc (constructor_decl : Types.constructor_declaration ) ->
1503
+ match constructor_decl.cd_args with
1504
+ | Cstr_tuple type_exprs ->
1505
+ type_exprs
1506
+ |> List. fold_left
1507
+ (fun acc type_expr ->
1508
+ acc
1509
+ @ extractRelevantTypesFromTypeExpr ~depth: 1 type_expr)
1510
+ acc
1511
+ | Cstr_record label_declarations ->
1512
+ label_declarations
1513
+ |> List. fold_left
1514
+ (fun acc (label_decl : Types.label_declaration ) ->
1515
+ acc
1516
+ @ extractRelevantTypesFromTypeExpr ~depth: 1
1517
+ label_decl.ld_type)
1518
+ acc)
1519
+ []
1520
+ | Type_abstract | Type_open -> [] )
1521
+ in
1522
+
1523
+ match input with
1524
+ | TypeExpr {typeExpr; name; env} ->
1525
+ let aliases = followTypeAliases [] typeExpr in
1526
+ let mainTypesRaw = TypeExpr {typeExpr; name; env} :: aliases in
1527
+
1528
+ (* Extract related types from the final concrete type *)
1529
+ let finalConcreteType = findFinalConcreteType typeExpr in
1530
+ let relatedTypesRaw =
1531
+ extractRelevantTypesFromTypeExpr finalConcreteType
1532
+ in
1533
+
1534
+ let mainTypes, relatedTypes =
1535
+ deduplicateAndRemoveAlreadyPresent mainTypesRaw relatedTypesRaw
1536
+ in
1537
+ {mainTypes; relatedTypes}
1538
+ | TypeDecl {typeDecl} ->
1539
+ let mainTypes = [input] in
1540
+ let relatedTypesRaw = extractRelevantTypesFromTypeDecl typeDecl in
1541
+
1542
+ let _, relatedTypes =
1543
+ deduplicateAndRemoveAlreadyPresent mainTypes relatedTypesRaw
1544
+ in
1545
+ {mainTypes; relatedTypes}
1546
+ end
0 commit comments