Skip to content

Commit 94a2dfc

Browse files
authored
Handle result type as a builtin (#860)
* handle result type as a builtin * changelog
1 parent 4db8c98 commit 94a2dfc

File tree

6 files changed

+170
-1
lines changed

6 files changed

+170
-1
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
1313
## master
1414

15+
#### :bug: Bug Fix
16+
17+
- Treat `result` type as a proper built in type. https://github.com/rescript-lang/rescript-vscode/pull/860
18+
1519
#### :nail_care: Polish
1620

1721
- Change end position of cursor when completing `Some(<fieldName>)` in patterns. https://github.com/rescript-lang/rescript-vscode/pull/857
1822

19-
2023
#### :bug: Bug Fix
2124

2225
- Add support for detecting dead fields inside inline records. https://github.com/rescript-lang/rescript-vscode/pull/858

analysis/src/CompletionBackEnd.ml

+67
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,71 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
12831283
| _ -> [noneCase; someAnyCase]
12841284
in
12851285
completions @ expandedCompletions |> filterItems ~prefix
1286+
| Tresult {env; okType; errorType} ->
1287+
let okInnerType =
1288+
okType |> TypeUtils.extractType ~env ~package:full.package
1289+
in
1290+
let errorInnerType =
1291+
errorType |> TypeUtils.extractType ~env ~package:full.package
1292+
in
1293+
let expandedOkCompletions =
1294+
match okInnerType with
1295+
| None -> []
1296+
| Some innerType ->
1297+
innerType
1298+
|> completeTypedValue ~full ~prefix ~completionContext ~mode
1299+
|> List.map (fun (c : Completion.t) ->
1300+
{
1301+
c with
1302+
name = "Ok(" ^ c.name ^ ")";
1303+
sortText = None;
1304+
insertText =
1305+
(match c.insertText with
1306+
| None -> None
1307+
| Some insertText -> Some ("Ok(" ^ insertText ^ ")"));
1308+
})
1309+
in
1310+
let expandedErrorCompletions =
1311+
match errorInnerType with
1312+
| None -> []
1313+
| Some innerType ->
1314+
innerType
1315+
|> completeTypedValue ~full ~prefix ~completionContext ~mode
1316+
|> List.map (fun (c : Completion.t) ->
1317+
{
1318+
c with
1319+
name = "Error(" ^ c.name ^ ")";
1320+
sortText = None;
1321+
insertText =
1322+
(match c.insertText with
1323+
| None -> None
1324+
| Some insertText -> Some ("Error(" ^ insertText ^ ")"));
1325+
})
1326+
in
1327+
let okAnyCase =
1328+
Completion.createWithSnippet ~name:"Ok(_)" ~kind:(Value okType) ~env
1329+
~insertText:"Ok(${1:_})" ()
1330+
in
1331+
let errorAnyCase =
1332+
Completion.createWithSnippet ~name:"Error(_)" ~kind:(Value errorType) ~env
1333+
~insertText:"Error(${1:_})" ()
1334+
in
1335+
let completions =
1336+
match completionContext with
1337+
| Some (Completable.CameFromRecordField fieldName) ->
1338+
[
1339+
Completion.createWithSnippet
1340+
~name:("Ok(" ^ fieldName ^ ")")
1341+
~kind:(Value okType) ~env
1342+
~insertText:("Ok(" ^ fieldName ^ ")$0")
1343+
();
1344+
okAnyCase;
1345+
errorAnyCase;
1346+
]
1347+
| _ -> [okAnyCase; errorAnyCase]
1348+
in
1349+
completions @ expandedOkCompletions @ expandedErrorCompletions
1350+
|> filterItems ~prefix
12861351
| Tuple (env, exprs, typ) ->
12871352
let numExprs = List.length exprs in
12881353
[
@@ -1715,6 +1780,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
17151780
| _ -> "(_)"))
17161781
| Some (Toption (_env, _typ)) ->
17171782
withExhaustiveItem c ~cases:["Some($1)"; "None"] ~startIndex:1
1783+
| Some (Tresult _) ->
1784+
withExhaustiveItem c ~cases:["Ok($1)"; "Error($1)"] ~startIndex:1
17181785
| Some (Tbool _) -> withExhaustiveItem c ~cases:["true"; "false"]
17191786
| _ -> [c])
17201787
| _ -> [c])

analysis/src/SharedTypes.ml

+5
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@ and completionType =
319319
| Texn of QueryEnv.t
320320
| Tpromise of QueryEnv.t * Types.type_expr
321321
| Toption of QueryEnv.t * innerType
322+
| Tresult of {
323+
env: QueryEnv.t;
324+
okType: Types.type_expr;
325+
errorType: Types.type_expr;
326+
}
322327
| Tbool of QueryEnv.t
323328
| Tarray of QueryEnv.t * innerType
324329
| Tstring of QueryEnv.t

analysis/src/TypeUtils.ml

+55
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ let rec extractType ~env ~package (t : Types.type_expr) =
119119
Some (Tpromise (env, payloadTypeExpr))
120120
| Tconstr (Path.Pident {name = "array"}, [payloadTypeExpr], _) ->
121121
Some (Tarray (env, TypeExpr payloadTypeExpr))
122+
| Tconstr (Path.Pident {name = "result"}, [okType; errorType], _) ->
123+
Some (Tresult {env; okType; errorType})
122124
| Tconstr (Path.Pident {name = "bool"}, [], _) -> Some (Tbool env)
123125
| Tconstr (Path.Pident {name = "string"}, [], _) -> Some (Tstring env)
124126
| Tconstr (Path.Pident {name = "exn"}, [], _) -> Some (Texn env)
@@ -362,6 +364,15 @@ let rec resolveNested ~env ~full ~nested ?ctx (typ : completionType) =
362364
typ
363365
|> extractType ~env ~package:full.package
364366
|> Utils.Option.flatMap (fun t -> t |> resolveNested ~env ~full ~nested)
367+
| NVariantPayload {constructorName = "Ok"; itemNum = 0}, Tresult {okType} ->
368+
okType
369+
|> extractType ~env ~package:full.package
370+
|> Utils.Option.flatMap (fun t -> t |> resolveNested ~env ~full ~nested)
371+
| ( NVariantPayload {constructorName = "Error"; itemNum = 0},
372+
Tresult {errorType} ) ->
373+
errorType
374+
|> extractType ~env ~package:full.package
375+
|> Utils.Option.flatMap (fun t -> t |> resolveNested ~env ~full ~nested)
365376
| ( NVariantPayload {constructorName; itemNum},
366377
Tvariant {env; constructors; typeParams; typeArgs} ) -> (
367378
match
@@ -481,6 +492,12 @@ let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
481492
| ( NVariantPayload {constructorName = "Some"; itemNum = 0},
482493
Toption (env, typ) ) ->
483494
Some (typ, env)
495+
| ( NVariantPayload {constructorName = "Ok"; itemNum = 0},
496+
Tresult {env; okType} ) ->
497+
Some (TypeExpr okType, env)
498+
| ( NVariantPayload {constructorName = "Error"; itemNum = 0},
499+
Tresult {env; errorType} ) ->
500+
Some (TypeExpr errorType, env)
484501
| NArray, Tarray (env, typ) -> Some (typ, env)
485502
| _ -> None))
486503
| patternPath :: nested -> (
@@ -527,6 +544,12 @@ let rec resolveNestedPatternPath (typ : innerType) ~env ~full ~nested =
527544
| ( NVariantPayload {constructorName = "Some"; itemNum = 0},
528545
Toption (env, typ) ) ->
529546
typ |> resolveNestedPatternPath ~env ~full ~nested
547+
| ( NVariantPayload {constructorName = "Ok"; itemNum = 0},
548+
Tresult {env; okType} ) ->
549+
TypeExpr okType |> resolveNestedPatternPath ~env ~full ~nested
550+
| ( NVariantPayload {constructorName = "Error"; itemNum = 0},
551+
Tresult {env; errorType} ) ->
552+
TypeExpr errorType |> resolveNestedPatternPath ~env ~full ~nested
530553
| NArray, Tarray (env, typ) ->
531554
typ |> resolveNestedPatternPath ~env ~full ~nested
532555
| _ -> None))
@@ -613,6 +636,10 @@ let rec extractedTypeToString ?(inner = false) = function
613636
"array<" ^ extractedTypeToString ~inner:true innerTyp ^ ">"
614637
| Toption (_, TypeExpr innerTyp) ->
615638
"option<" ^ Shared.typeToString innerTyp ^ ">"
639+
| Tresult {okType; errorType} ->
640+
"result<" ^ Shared.typeToString okType ^ ", "
641+
^ Shared.typeToString errorType
642+
^ ">"
616643
| Toption (_, ExtractedType innerTyp) ->
617644
"option<" ^ extractedTypeToString ~inner:true innerTyp ^ ">"
618645
| Tpromise (_, innerTyp) -> "promise<" ^ Shared.typeToString innerTyp ^ ">"
@@ -687,6 +714,34 @@ module Codegen = struct
687714
@ (expandedBranches
688715
|> List.map (fun (pat : Parsetree.pattern) ->
689716
mkConstructPat ~payload:pat "Some")))
717+
| Tresult {okType; errorType} ->
718+
let extractedOkType = okType |> extractType ~env ~package:full.package in
719+
let extractedErrorType =
720+
errorType |> extractType ~env ~package:full.package
721+
in
722+
let expandedOkBranches =
723+
match extractedOkType with
724+
| None -> []
725+
| Some extractedType -> (
726+
match extractedTypeToExhaustivePatterns ~env ~full extractedType with
727+
| None -> []
728+
| Some patterns -> patterns)
729+
in
730+
let expandedErrorBranches =
731+
match extractedErrorType with
732+
| None -> []
733+
| Some extractedType -> (
734+
match extractedTypeToExhaustivePatterns ~env ~full extractedType with
735+
| None -> []
736+
| Some patterns -> patterns)
737+
in
738+
Some
739+
((expandedOkBranches
740+
|> List.map (fun (pat : Parsetree.pattern) ->
741+
mkConstructPat ~payload:pat "Ok"))
742+
@ (expandedErrorBranches
743+
|> List.map (fun (pat : Parsetree.pattern) ->
744+
mkConstructPat ~payload:pat "Error")))
690745
| Tbool _ -> Some [mkConstructPat "true"; mkConstructPat "false"]
691746
| _ -> None
692747

analysis/tests/src/CompletionPattern.res

+3
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,6 @@ let res: result<someVariant, somePolyVariant> = Ok(One)
216216

217217
// switch res { | Ok() }
218218
// ^com
219+
220+
// switch res { | Error() }
221+
// ^com

analysis/tests/src/expected/CompletionPattern.res.txt

+36
Original file line numberDiff line numberDiff line change
@@ -1141,3 +1141,39 @@ Path res
11411141
"insertTextFormat": 2
11421142
}]
11431143

1144+
Complete src/CompletionPattern.res 219:24
1145+
posCursor:[219:24] posNoWhite:[219:23] Found pattern:[219:18->219:25]
1146+
Ppat_construct Error:[219:18->219:23]
1147+
posCursor:[219:24] posNoWhite:[219:23] Found pattern:[219:23->219:25]
1148+
Ppat_construct ():[219:23->219:25]
1149+
Completable: Cpattern Value[res]->variantPayload::Error($0)
1150+
Package opens Pervasives.JsxModules.place holder
1151+
Resolved opens 1 pervasives
1152+
ContextPath Value[res]
1153+
Path res
1154+
[{
1155+
"label": "#one",
1156+
"kind": 4,
1157+
"tags": [],
1158+
"detail": "#one\n\n[#one | #three(someRecord, bool) | #two(bool)]",
1159+
"documentation": null,
1160+
"insertText": "#one",
1161+
"insertTextFormat": 2
1162+
}, {
1163+
"label": "#three(_, _)",
1164+
"kind": 4,
1165+
"tags": [],
1166+
"detail": "#three(someRecord, bool)\n\n[#one | #three(someRecord, bool) | #two(bool)]",
1167+
"documentation": null,
1168+
"insertText": "#three(${1:_}, ${2:_})",
1169+
"insertTextFormat": 2
1170+
}, {
1171+
"label": "#two(_)",
1172+
"kind": 4,
1173+
"tags": [],
1174+
"detail": "#two(bool)\n\n[#one | #three(someRecord, bool) | #two(bool)]",
1175+
"documentation": null,
1176+
"insertText": "#two(${1:_})",
1177+
"insertTextFormat": 2
1178+
}]
1179+

0 commit comments

Comments
 (0)