Skip to content

Commit 3e95a89

Browse files
authored
Merge branch 'master' into fix-markdown-divider-render
2 parents 814a710 + 3e2076e commit 3e95a89

22 files changed

+314
-144
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
## master
1414

1515
#### :nail_care: Polish
16+
1617
- Remove spacing between type definition in clients that do not support markdown links. https://github.com/rescript-lang/rescript-vscode/pull/619
1718

19+
- Rename custom LSP methods names. https://github.com/rescript-lang/rescript-vscode/pull/611
20+
1821
#### :bug: Bug Fix
1922

2023
- Fix issue where `-open Some.Path` in `"bsc-flags"` would sometimes be treated differently from `open Some.Path` locally in a file https://github.com/rescript-lang/rescript-vscode/pull/616
2124

25+
- Fix issue where doc comment is not shown on hover in case of shadowed identifier (in particular for JSX V4 components which shadow `make`) https://github.com/rescript-lang/rescript-vscode/issues/621
26+
27+
- Adapt command to create interface files to latest JSX V4 (no key prop, possibly empty record) https://github.com/rescript-lang/rescript-vscode/issues/617
28+
29+
- Fix issue where pipes were not taken into account in the signature help, resulting in the highlighted argument in signature help always being off by one for unlabelled arguments in piped expressions https://github.com/rescript-lang/rescript-vscode/issues/618
30+
31+
- Fix file location in Document Symbols response. https://github.com/rescript-lang/rescript-vscode/issues/629
32+
2233
## v1.8.2
2334

2435
#### :rocket: New Feature

analysis/src/CompletionBackEnd.ml

+19-5
Original file line numberDiff line numberDiff line change
@@ -1283,10 +1283,18 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos
12831283
|> completionsGetTypeEnv
12841284
with
12851285
| Some (typ, _envNotUsed) -> (
1286-
let arrayModulePath = ["Js"; "Array2"] in
1287-
let listModulePath = ["Belt"; "List"] in
1288-
let optionModulePath = ["Belt"; "Option"] in
1289-
let stringModulePath = ["Js"; "String2"] in
1286+
let {
1287+
arrayModulePath;
1288+
optionModulePath;
1289+
stringModulePath;
1290+
intModulePath;
1291+
floatModulePath;
1292+
promiseModulePath;
1293+
listModulePath;
1294+
resultModulePath;
1295+
} =
1296+
package.builtInCompletionModules
1297+
in
12901298
let getModulePath path =
12911299
let rec loop (path : Path.t) =
12921300
match path with
@@ -1296,9 +1304,15 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos
12961304
in
12971305
match path with
12981306
| Path.Pident id when Ident.name id = "array" -> arrayModulePath
1299-
| Path.Pident id when Ident.name id = "list" -> listModulePath
13001307
| Path.Pident id when Ident.name id = "option" -> optionModulePath
13011308
| Path.Pident id when Ident.name id = "string" -> stringModulePath
1309+
| Path.Pident id when Ident.name id = "int" -> intModulePath
1310+
| Path.Pident id when Ident.name id = "float" -> floatModulePath
1311+
| Path.Pident id when Ident.name id = "promise" -> promiseModulePath
1312+
| Path.Pident id when Ident.name id = "list" -> listModulePath
1313+
| Path.Pident id when Ident.name id = "result" -> resultModulePath
1314+
| Path.Pident id when Ident.name id = "lazy_t" -> ["Lazy"]
1315+
| Path.Pident id when Ident.name id = "char" -> ["Char"]
13021316
| _ -> (
13031317
match loop path with
13041318
| _ :: rest -> List.rev rest

analysis/src/CreateInterface.ml

+13-7
Original file line numberDiff line numberDiff line change
@@ -240,16 +240,19 @@ let printSignature ~extractor ~signature =
240240
( propsId,
241241
{
242242
type_params;
243-
type_kind = Type_record (labelDecls, Record_optional_labels optLbls);
243+
type_kind = Type_record (labelDecls, recordRepresentation);
244244
},
245245
_ )
246246
:: Sig_value (makeId (* make *), makeValueDesc)
247247
:: rest
248248
when Ident.name propsId = "props"
249249
&& getComponentTypeV4 makeValueDesc.val_type <> None
250-
&& optLbls |> List.mem "key" ->
250+
&&
251+
match recordRepresentation with
252+
| Record_optional_labels _ -> true
253+
| _ -> labelDecls = [] (* empty record *) ->
251254
(* PPX V4 component declaration:
252-
type props = {..., key?: _}
255+
type props = {...}
253256
let v = ...
254257
*)
255258
let newItemStr =
@@ -268,15 +271,18 @@ let printSignature ~extractor ~signature =
268271
in
269272
let lblName = labelDecl.ld_id |> Ident.name in
270273
let lbl =
274+
let optLbls =
275+
match recordRepresentation with
276+
| Record_optional_labels optLbls -> optLbls
277+
| _ -> []
278+
in
271279
if List.mem lblName optLbls then Asttypes.Optional lblName
272280
else Labelled lblName
273281
in
274-
if lblName = "key" then mkFunType rest
275-
else
276-
{retType with desc = Tarrow (lbl, propType, mkFunType rest, Cok)}
282+
{retType with desc = Tarrow (lbl, propType, mkFunType rest, Cok)}
277283
in
278284
let funType =
279-
if List.length labelDecls = 1 (* No props: only "key "*) then
285+
if List.length labelDecls = 0 (* No props *) then
280286
let tUnit =
281287
Ctype.newconstr (Path.Pident (Ident.create "unit")) []
282288
in

analysis/src/DocumentSymbol.ml

+2-9
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,9 @@ let command ~path =
137137
let result =
138138
!symbols
139139
|> List.rev_map (fun (name, loc, kind) ->
140+
let range = Utils.cmtLocToRange loc in
140141
Protocol.stringifyDocumentSymbolItem
141-
{
142-
name;
143-
location =
144-
{
145-
uri = Uri.toString (Uri.fromPath path);
146-
range = Utils.cmtLocToRange loc;
147-
};
148-
kind = kindNumber kind;
149-
})
142+
{name; range; selectionRange = range; kind = kindNumber kind})
150143
|> String.concat ",\n"
151144
in
152145
print_endline ("[\n" ^ result ^ "\n]")

analysis/src/Packages.ml

+30
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,36 @@ let newBsPackage ~rootPath =
9393
pathsForModule;
9494
opens;
9595
namespace;
96+
builtInCompletionModules =
97+
(if
98+
opens_from_bsc_flags
99+
|> List.find_opt (fun opn ->
100+
match opn with
101+
| ["RescriptStdlib"] -> true
102+
| _ -> false)
103+
|> Option.is_some
104+
then
105+
{
106+
arrayModulePath = ["Array"];
107+
optionModulePath = ["Option"];
108+
stringModulePath = ["String"];
109+
intModulePath = ["Int"];
110+
floatModulePath = ["Float"];
111+
promiseModulePath = ["Promise"];
112+
listModulePath = ["List"];
113+
resultModulePath = ["Result"];
114+
}
115+
else
116+
{
117+
arrayModulePath = ["Js"; "Array2"];
118+
optionModulePath = ["Belt"; "Option"];
119+
stringModulePath = ["Js"; "String2"];
120+
intModulePath = ["Belt"; "Int"];
121+
floatModulePath = ["Belt"; "Float"];
122+
promiseModulePath = ["Js"; "Promise"];
123+
listModulePath = ["Belt"; "List"];
124+
resultModulePath = ["Belt"; "Result"];
125+
});
96126
})))
97127
| None -> None)
98128

analysis/src/ProcessCmt.ml

+14-2
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,30 @@ let addDeclared ~(name : string Location.loc) ~extent ~stamp ~(env : Env.t)
1010
addStamp env.stamps stamp declared;
1111
declared
1212

13-
let rec forTypeSignatureItem ~env ~(exported : Exported.t)
13+
let rec forTypeSignatureItem ~(env : SharedTypes.Env.t) ~(exported : Exported.t)
1414
(item : Types.signature_item) =
1515
match item with
1616
| Sig_value (ident, {val_type; val_attributes; val_loc = loc}) ->
1717
let item = val_type in
18+
let stamp = Ident.binding_time ident in
19+
let oldDeclared = Stamps.findValue env.stamps stamp in
1820
let declared =
1921
addDeclared
2022
~name:(Location.mknoloc (Ident.name ident))
21-
~extent:loc ~stamp:(Ident.binding_time ident) ~env ~item val_attributes
23+
~extent:loc ~stamp ~env ~item val_attributes
2224
(Exported.add exported Exported.Value)
2325
Stamps.addValue
2426
in
27+
let declared =
28+
(* When an id is shadowed, a module constraint without the doc comment is created.
29+
Here the existing doc comment is restored. See https://github.com/rescript-lang/rescript-vscode/issues/621 *)
30+
match oldDeclared with
31+
| Some oldDeclared when declared.docstring = [] ->
32+
let newDeclared = {declared with docstring = oldDeclared.docstring} in
33+
Stamps.addValue env.stamps stamp newDeclared;
34+
newDeclared
35+
| _ -> declared
36+
in
2537
[{Module.kind = Module.Value declared.item; name = declared.name.txt}]
2638
| Sig_type
2739
( ident,

analysis/src/Protocol.ml

+11-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ type completionItem = {
4242
}
4343

4444
type location = {uri: string; range: range}
45-
type documentSymbolItem = {name: string; kind: int; location: location}
45+
type documentSymbolItem = {
46+
name: string;
47+
kind: int;
48+
range: range;
49+
selectionRange: range;
50+
}
4651
type renameFile = {oldUri: string; newUri: string}
4752
type textEdit = {range: range; newText: string}
4853

@@ -103,15 +108,16 @@ let stringifyLocation (h : location) =
103108
Printf.sprintf {|{"uri": "%s", "range": %s}|} (Json.escape h.uri)
104109
(stringifyRange h.range)
105110

106-
let stringifyDocumentSymbolItem i =
111+
let stringifyDocumentSymbolItem (i : documentSymbolItem) =
112+
let range = stringifyRange i.range in
107113
Printf.sprintf
108114
{|{
109115
"name": "%s",
110116
"kind": %i,
111-
"location": %s
117+
"range": %s,
118+
"selectionRange": %s
112119
}|}
113-
(Json.escape i.name) i.kind
114-
(stringifyLocation i.location)
120+
(Json.escape i.name) i.kind range range
115121

116122
let stringifyRenameFile {oldUri; newUri} =
117123
Printf.sprintf {|{

analysis/src/SharedTypes.ml

+12
Original file line numberDiff line numberDiff line change
@@ -361,12 +361,24 @@ type file = string
361361

362362
module FileSet = Set.Make (String)
363363

364+
type builtInCompletionModules = {
365+
arrayModulePath: string list;
366+
optionModulePath: string list;
367+
stringModulePath: string list;
368+
intModulePath: string list;
369+
floatModulePath: string list;
370+
promiseModulePath: string list;
371+
listModulePath: string list;
372+
resultModulePath: string list;
373+
}
374+
364375
type package = {
365376
rootPath: filePath;
366377
projectFiles: FileSet.t;
367378
dependenciesFiles: FileSet.t;
368379
pathsForModule: (file, paths) Hashtbl.t;
369380
namespace: string option;
381+
builtInCompletionModules: builtInCompletionModules;
370382
opens: path list;
371383
}
372384

analysis/src/SignatureHelp.ml

+61-36
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,68 @@ let signatureHelp ~path ~pos ~currentFile ~debug =
154154
let posBeforeCursor = Pos.posBeforeCursor pos in
155155
let supportsMarkdownLinks = true in
156156
let foundFunctionApplicationExpr = ref None in
157-
let setFound r = foundFunctionApplicationExpr := Some r in
157+
let setFound r =
158+
if !foundFunctionApplicationExpr = None then
159+
foundFunctionApplicationExpr := Some r
160+
in
161+
let searchForArgWithCursor ~isPipeExpr ~args ~exp =
162+
let extractedArgs = extractExpApplyArgs ~args in
163+
let argAtCursor =
164+
let unlabelledArgCount = ref (if isPipeExpr then 1 else 0) in
165+
extractedArgs
166+
|> List.find_map (fun arg ->
167+
match arg.label with
168+
| None ->
169+
let currentUnlabelledArgCount = !unlabelledArgCount in
170+
unlabelledArgCount := currentUnlabelledArgCount + 1;
171+
(* An argument without a label is just the expression, so we can use that. *)
172+
if arg.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then
173+
Some (Unlabelled currentUnlabelledArgCount)
174+
else None
175+
| Some {name; posStart; posEnd} -> (
176+
(* Check for the label identifier itself having the cursor *)
177+
match
178+
pos |> CursorPosition.classifyPositions ~posStart ~posEnd
179+
with
180+
| HasCursor -> Some (Labelled name)
181+
| NoCursor | EmptyLoc -> (
182+
(* If we're not in the label, check the exp. Either the exp
183+
exists and has the cursor. Or the exp is a parser recovery
184+
node, in which case we assume that the parser recovery
185+
indicates that the cursor was here. *)
186+
match
187+
( arg.exp.pexp_desc,
188+
arg.exp.pexp_loc
189+
|> CursorPosition.classifyLoc ~pos:posBeforeCursor )
190+
with
191+
| Pexp_extension ({txt = "rescript.exprhole"}, _), _
192+
| _, HasCursor ->
193+
Some (Labelled name)
194+
| _ -> None)))
195+
in
196+
setFound (argAtCursor, exp, extractedArgs)
197+
in
158198
let expr (iterator : Ast_iterator.iterator) (expr : Parsetree.expression) =
159199
(match expr with
200+
(* Handle pipes, like someVar->someFunc(... *)
201+
| {
202+
pexp_desc =
203+
Pexp_apply
204+
( {pexp_desc = Pexp_ident {txt = Lident "|."}},
205+
[
206+
_;
207+
( _,
208+
{
209+
pexp_desc =
210+
Pexp_apply (({pexp_desc = Pexp_ident _} as exp), args);
211+
pexp_loc;
212+
} );
213+
] );
214+
}
215+
when pexp_loc
216+
|> CursorPosition.classifyLoc ~pos:posBeforeCursor
217+
== HasCursor ->
218+
searchForArgWithCursor ~isPipeExpr:true ~args ~exp
160219
(* Look for applying idents, like someIdent(...) *)
161220
| {
162221
pexp_desc = Pexp_apply (({pexp_desc = Pexp_ident _} as exp), args);
@@ -165,41 +224,7 @@ let signatureHelp ~path ~pos ~currentFile ~debug =
165224
when pexp_loc
166225
|> CursorPosition.classifyLoc ~pos:posBeforeCursor
167226
== HasCursor ->
168-
let extractedArgs = extractExpApplyArgs ~args in
169-
let argAtCursor =
170-
let unlabelledArgCount = ref 0 in
171-
extractedArgs
172-
|> List.find_map (fun arg ->
173-
match arg.label with
174-
| None ->
175-
let currentUnlabelledArgCount = !unlabelledArgCount in
176-
unlabelledArgCount := currentUnlabelledArgCount + 1;
177-
(* An argument without a label is just the expression, so we can use that. *)
178-
if arg.exp.pexp_loc |> Loc.hasPos ~pos:posBeforeCursor then
179-
Some (Unlabelled currentUnlabelledArgCount)
180-
else None
181-
| Some {name; posStart; posEnd} -> (
182-
(* Check for the label identifier itself having the cursor *)
183-
match
184-
pos |> CursorPosition.classifyPositions ~posStart ~posEnd
185-
with
186-
| HasCursor -> Some (Labelled name)
187-
| NoCursor | EmptyLoc -> (
188-
(* If we're not in the label, check the exp. Either the exp
189-
exists and has the cursor. Or the exp is a parser recovery
190-
node, in which case we assume that the parser recovery
191-
indicates that the cursor was here. *)
192-
match
193-
( arg.exp.pexp_desc,
194-
arg.exp.pexp_loc
195-
|> CursorPosition.classifyLoc ~pos:posBeforeCursor )
196-
with
197-
| Pexp_extension ({txt = "rescript.exprhole"}, _), _
198-
| _, HasCursor ->
199-
Some (Labelled name)
200-
| _ -> None)))
201-
in
202-
setFound (argAtCursor, exp, extractedArgs)
227+
searchForArgWithCursor ~isPipeExpr:false ~args ~exp
203228
| _ -> ());
204229
Ast_iterator.default_iterator.expr iterator expr
205230
in

0 commit comments

Comments
 (0)