Skip to content

Commit e11dfe3

Browse files
authored
Track scope properly when inferring values (#869)
* add reprod * change to hover * track scope properly when inferring values * changelog
1 parent 9d38eb2 commit e11dfe3

8 files changed

+64
-39
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
- Proper default for `"uncurried"` in V11 projects. https://github.com/rescript-lang/rescript-vscode/pull/867
2222
- Treat `result` type as a proper built in type. https://github.com/rescript-lang/rescript-vscode/pull/860
23+
- Fix infinite loop when resolving inferred completions when several values in scope has the same name. https://github.com/rescript-lang/rescript-vscode/pull/869
2324

2425
#### :nail_care: Polish
2526

analysis/src/CompletionBackEnd.ml

+20-22
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed
263263
completionForExportedFields ~env ~prefix ~exact ~namesUsed
264264
@ completionForExportedModules ~env ~prefix ~exact ~namesUsed
265265

266-
let processLocalValue name loc contextPath ~prefix ~exact ~env
266+
let processLocalValue name loc contextPath scope ~prefix ~exact ~env
267267
~(localTables : LocalTables.t) =
268268
if Utils.checkName name ~prefix ~exact then
269269
match Hashtbl.find_opt localTables.valueTable (name, Loc.start loc) with
@@ -279,14 +279,14 @@ let processLocalValue name loc contextPath ~prefix ~exact ~env
279279
}
280280
:: localTables.resultRev)
281281
| None ->
282-
Log.log
283-
(Printf.sprintf "Completion Value Not Found %s loc:%s\n" name
284-
(Loc.toString loc));
282+
if !Cfg.debugFollowCtxPath then
283+
Printf.printf "Completion Value Not Found %s loc:%s\n" name
284+
(Loc.toString loc);
285285
localTables.resultRev <-
286286
Completion.create name ~env
287287
~kind:
288288
(match contextPath with
289-
| Some contextPath -> FollowContextPath contextPath
289+
| Some contextPath -> FollowContextPath (contextPath, scope)
290290
| None ->
291291
Value
292292
(Ctype.newconstr
@@ -622,17 +622,17 @@ let completionsGetCompletionType ~full = function
622622
| {Completion.kind = ExtractedType (typ, _); env} :: _ -> Some (typ, env)
623623
| _ -> None
624624

625-
let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos ~scope
626-
= function
625+
let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos =
626+
function
627627
| {Completion.kind = Value typ; env} :: _
628628
| {Completion.kind = ObjLabel typ; env} :: _
629629
| {Completion.kind = Field ({typ}, _); env} :: _ ->
630630
Some (TypeExpr typ, env)
631-
| {Completion.kind = FollowContextPath ctxPath; env} :: _ ->
631+
| {Completion.kind = FollowContextPath (ctxPath, scope); env} :: _ ->
632632
ctxPath
633633
|> getCompletionsForContextPath ~debug ~full ~env ~exact:true ~opens
634634
~rawOpens ~pos ~scope
635-
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos ~scope
635+
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
636636
| {Completion.kind = Type typ; env} :: _ -> (
637637
match TypeUtils.extractTypeFromResolvedType typ ~env ~full with
638638
| None -> None
@@ -642,16 +642,16 @@ let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos ~scope
642642
| _ -> None
643643

644644
and completionsGetTypeEnv2 ~debug (completions : Completion.t list) ~full ~opens
645-
~rawOpens ~pos ~scope =
645+
~rawOpens ~pos =
646646
match completions with
647647
| {Completion.kind = Value typ; env} :: _ -> Some (typ, env)
648648
| {Completion.kind = ObjLabel typ; env} :: _ -> Some (typ, env)
649649
| {Completion.kind = Field ({typ}, _); env} :: _ -> Some (typ, env)
650-
| {Completion.kind = FollowContextPath ctxPath; env} :: _ ->
650+
| {Completion.kind = FollowContextPath (ctxPath, scope); env} :: _ ->
651651
ctxPath
652652
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
653653
~exact:true ~scope
654-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
654+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
655655
| _ -> None
656656

657657
and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
@@ -754,7 +754,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
754754
cp
755755
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
756756
~exact:true ~scope
757-
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos ~scope
757+
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
758758
with
759759
| Some ((TypeExpr typ | ExtractedType (Tfunction {typ})), env) -> (
760760
let rec reconstructFunctionType args tRet =
@@ -805,7 +805,6 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
805805
match
806806
completionsForCtxPath
807807
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
808-
~scope
809808
with
810809
| Some (TypeExpr typ, env) -> (
811810
match typ |> TypeUtils.extractRecordType ~env ~package with
@@ -839,7 +838,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
839838
cp
840839
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
841840
~exact:true ~scope
842-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
841+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
843842
with
844843
| Some (typ, env) -> (
845844
match typ |> TypeUtils.extractObjectType ~env ~package with
@@ -866,7 +865,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
866865
cp
867866
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
868867
~exact:true ~scope ~mode:Pipe
869-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
868+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
870869
with
871870
| None -> []
872871
| Some (typ, envFromCompletionItem) -> (
@@ -1031,7 +1030,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
10311030
path
10321031
|> getCompletionsForPath ~debug ~completionContext:Value ~exact:true
10331032
~package ~opens ~full ~pos ~env ~scope
1034-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
1033+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
10351034
in
10361035
let lowercaseComponent =
10371036
match pathToComponent with
@@ -1078,7 +1077,6 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
10781077
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
10791078
~exact:true ~scope
10801079
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
1081-
~scope
10821080
with
10831081
| Some ((TypeExpr typ | ExtractedType (Tfunction {typ})), env) ->
10841082
(typ |> TypeUtils.getArgs ~full ~env, env)
@@ -1115,7 +1113,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
11151113
rootCtxPath
11161114
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
11171115
~exact:true ~scope
1118-
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos ~scope
1116+
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
11191117
with
11201118
| Some (typ, env) -> (
11211119
match typ |> TypeUtils.resolveNestedPatternPath ~env ~full ~nested with
@@ -1528,7 +1526,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
15281526
path
15291527
|> getCompletionsForPath ~debug ~completionContext:Value ~exact:true
15301528
~package ~opens ~full ~pos ~env ~scope
1531-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
1529+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
15321530
in
15331531
match completable with
15341532
| Cnone -> []
@@ -1603,7 +1601,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
16031601
cp
16041602
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
16051603
~exact:true ~scope
1606-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
1604+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
16071605
with
16081606
| Some (typ, _env) ->
16091607
if debug then
@@ -1639,7 +1637,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
16391637
contextPath
16401638
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
16411639
~exact:true ~scope
1642-
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~scope
1640+
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
16431641
with
16441642
| Some (typ, env) -> (
16451643
match

analysis/src/Hover.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ let getHoverViaCompletions ~debug ~path ~pos ~currentFile ~forHover
141141
let opens = CompletionBackEnd.getOpens ~debug ~rawOpens ~package ~env in
142142
match
143143
CompletionBackEnd.completionsGetTypeEnv2 ~debug ~full ~rawOpens ~opens
144-
~pos ~scope completions
144+
~pos completions
145145
with
146146
| Some (typ, _env) ->
147147
let typeString =
@@ -154,7 +154,7 @@ let getHoverViaCompletions ~debug ~path ~pos ~currentFile ~forHover
154154
let opens = CompletionBackEnd.getOpens ~debug ~rawOpens ~package ~env in
155155
match
156156
CompletionBackEnd.completionsGetTypeEnv2 ~debug ~full ~rawOpens ~opens
157-
~pos ~scope completions
157+
~pos completions
158158
with
159159
| Some (typ, _env) ->
160160
let typeString =

analysis/src/Scope.ml

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
type item =
2-
| Constructor of string * Location.t
3-
| Field of string * Location.t
4-
| Module of string * Location.t
5-
| Open of string list
6-
| Type of string * Location.t
7-
| Value of string * Location.t * SharedTypes.Completable.contextPath option
1+
type item = SharedTypes.ScopeTypes.item
82

93
type t = item list
104

5+
open SharedTypes.ScopeTypes
6+
117
let itemToString item =
128
let str s = if s = "" then "\"\"" else s in
139
let list l = "[" ^ (l |> List.map str |> String.concat ", ") ^ "]" in
@@ -16,7 +12,7 @@ let itemToString item =
1612
| Field (s, loc) -> "Field " ^ s ^ " " ^ Loc.toString loc
1713
| Open sl -> "Open " ^ list sl
1814
| Module (s, loc) -> "Module " ^ s ^ " " ^ Loc.toString loc
19-
| Value (s, loc, _) -> "Value " ^ s ^ " " ^ Loc.toString loc
15+
| Value (s, loc, _, _) -> "Value " ^ s ^ " " ^ Loc.toString loc
2016
| Type (s, loc) -> "Type " ^ s ^ " " ^ Loc.toString loc
2117
[@@live]
2218

@@ -34,14 +30,14 @@ let addValue ~name ~loc ?contextPath x =
3430
if showDebug then
3531
Printf.printf "adding value '%s' with ctxPath: %s\n" name
3632
(SharedTypes.Completable.contextPathToString contextPath));
37-
Value (name, loc, contextPath) :: x
33+
Value (name, loc, contextPath, x) :: x
3834
let addType ~name ~loc x = Type (name, loc) :: x
3935

4036
let iterValuesBeforeFirstOpen f x =
4137
let rec loop items =
4238
match items with
43-
| Value (s, loc, contextPath) :: rest ->
44-
f s loc contextPath;
39+
| Value (s, loc, contextPath, scope) :: rest ->
40+
f s loc contextPath scope;
4541
loop rest
4642
| Open _ :: _ -> ()
4743
| _ :: rest -> loop rest
@@ -52,8 +48,8 @@ let iterValuesBeforeFirstOpen f x =
5248
let iterValuesAfterFirstOpen f x =
5349
let rec loop foundOpen items =
5450
match items with
55-
| Value (s, loc, contextPath) :: rest ->
56-
if foundOpen then f s loc contextPath;
51+
| Value (s, loc, contextPath, scope) :: rest ->
52+
if foundOpen then f s loc contextPath scope;
5753
loop foundOpen rest
5854
| Open _ :: rest -> loop true rest
5955
| _ :: rest -> loop foundOpen rest

analysis/src/SharedTypes.ml

+11-1
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,16 @@ module Completable = struct
733733
| ChtmlElement {prefix} -> "ChtmlElement <" ^ prefix
734734
end
735735

736+
module ScopeTypes = struct
737+
type item =
738+
| Constructor of string * Location.t
739+
| Field of string * Location.t
740+
| Module of string * Location.t
741+
| Open of string list
742+
| Type of string * Location.t
743+
| Value of string * Location.t * Completable.contextPath option * item list
744+
end
745+
736746
module Completion = struct
737747
type kind =
738748
| Module of Module.t
@@ -746,7 +756,7 @@ module Completion = struct
746756
| FileModule of string
747757
| Snippet of string
748758
| ExtractedType of completionType * [`Value | `Type]
749-
| FollowContextPath of Completable.contextPath
759+
| FollowContextPath of Completable.contextPath * ScopeTypes.item list
750760

751761
type t = {
752762
name: string;

analysis/src/Xform.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ module ExhaustiveSwitch = struct
291291
in
292292
match
293293
CompletionBackEnd.completionsGetCompletionType2 ~debug ~full
294-
~rawOpens ~opens ~pos ~scope completions
294+
~rawOpens ~opens ~pos completions
295295
with
296296
| Some (typ, _env) ->
297297
let extractedType =

analysis/tests/src/CompletionInferValues.res

+5
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,8 @@ let fn3 = (~cb: sameFileRecord => unit) => {
162162
// But pipe completion gets the wrong completion path. Should be `ReactDOM.Client.Root.t`, but ends up being `CompletionSupport2.ReactDOM.Client.Root.t`.
163163
// let renderer = CompletionSupport2.makeRenderer(~prepare=() => "hello",~render=({support:{root}}) => {root->},())
164164
// ^com
165+
166+
// Handles reusing the same name already in scope for bindings
167+
let res = 1
168+
// switch res { | res => res }
169+
// ^hov

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

+15
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,18 @@ Path ReactDOM.Client.Root.
876876
"documentation": null
877877
}]
878878

879+
Hover src/CompletionInferValues.res 167:27
880+
Nothing at that position. Now trying to use completion.
881+
posCursor:[167:27] posNoWhite:[167:26] Found expr:[167:25->167:28]
882+
Pexp_ident res:[167:25->167:28]
883+
Completable: Cpath Value[res]
884+
Package opens Pervasives.JsxModules.place holder
885+
Resolved opens 1 pervasives
886+
ContextPath Value[res]
887+
Path res
888+
Package opens Pervasives.JsxModules.place holder
889+
Resolved opens 1 pervasives
890+
ContextPath Value[res]
891+
Path res
892+
{"contents": {"kind": "markdown", "value": "```rescript\nint\n```"}}
893+

0 commit comments

Comments
 (0)