Skip to content

Commit 794ae97

Browse files
aspeddrozth
authored andcommitted
support .res
1 parent efd93db commit 794ae97

File tree

6 files changed

+305
-84
lines changed

6 files changed

+305
-84
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
- Greatly extend completion abilities for unsaved code. WARNING: Might be a bit unstable initially. Report any issues you see. https://github.com/rescript-lang/rescript-vscode/pull/712
2020
- Provide hovers for more unsaved code via the new completion features. https://github.com/rescript-lang/rescript-vscode/pull/749
21+
- Docstring template Code Action. https://github.com/rescript-lang/rescript-vscode/pull/764
2122

2223
## 1.14.0
2324

Diff for: analysis/src/Xform.ml

+174-77
Original file line numberDiff line numberDiff line change
@@ -253,27 +253,6 @@ module AddTypeAnnotation = struct
253253
end
254254

255255
module AddDocTemplate = struct
256-
let mkIterator ~pos ~result =
257-
let signature_item (iterator : Ast_iterator.iterator)
258-
(item : Parsetree.signature_item) =
259-
match item.psig_desc with
260-
| Psig_value value_description as r
261-
when Loc.hasPos ~pos value_description.pval_loc
262-
&& ProcessAttributes.findDocAttribute
263-
value_description.pval_attributes
264-
= None ->
265-
result := Some (r, item.psig_loc)
266-
| Psig_type (_, hd :: _) as r
267-
when Loc.hasPos ~pos hd.ptype_loc
268-
&& ProcessAttributes.findDocAttribute hd.ptype_attributes = None ->
269-
result := Some (r, item.psig_loc)
270-
| Psig_module {pmd_name = {loc}} as r ->
271-
if Loc.start loc = pos then result := Some (r, item.psig_loc)
272-
else Ast_iterator.default_iterator.signature_item iterator item
273-
| _ -> Ast_iterator.default_iterator.signature_item iterator item
274-
in
275-
{Ast_iterator.default_iterator with signature_item}
276-
277256
let createTemplate () =
278257
let docContent = ["\n"; "\n"] in
279258
let expression =
@@ -295,61 +274,169 @@ module AddDocTemplate = struct
295274
in
296275
(Location.mkloc "res.doc" attrLoc, Parsetree.PStr [structureItem])
297276

298-
let processSigValue (vl_desc : Parsetree.value_description) loc =
299-
let attr = createTemplate () in
300-
let newValueBinding =
301-
{vl_desc with pval_attributes = attr :: vl_desc.pval_attributes}
302-
in
303-
let signature_item_desc = Parsetree.Psig_value newValueBinding in
304-
Ast_helper.Sig.mk ~loc signature_item_desc
277+
module Interface = struct
278+
let mkIterator ~pos ~result =
279+
let signature_item (iterator : Ast_iterator.iterator)
280+
(item : Parsetree.signature_item) =
281+
match item.psig_desc with
282+
| Psig_value value_description as r
283+
when Loc.hasPos ~pos value_description.pval_loc
284+
&& ProcessAttributes.findDocAttribute
285+
value_description.pval_attributes
286+
= None ->
287+
result := Some (r, item.psig_loc)
288+
| Psig_type (_, hd :: _) as r
289+
when Loc.hasPos ~pos hd.ptype_loc
290+
&& ProcessAttributes.findDocAttribute hd.ptype_attributes = None
291+
->
292+
result := Some (r, item.psig_loc)
293+
| Psig_module {pmd_name = {loc}} as r ->
294+
if Loc.start loc = pos then result := Some (r, item.psig_loc)
295+
else Ast_iterator.default_iterator.signature_item iterator item
296+
| _ -> Ast_iterator.default_iterator.signature_item iterator item
297+
in
298+
{Ast_iterator.default_iterator with signature_item}
305299

306-
let processTypeDecl (typ : Parsetree.type_declaration) =
307-
let attr = createTemplate () in
308-
let newTypeDeclaration =
309-
{typ with ptype_attributes = attr :: typ.ptype_attributes}
310-
in
311-
newTypeDeclaration
300+
let processSigValue (valueDesc : Parsetree.value_description) loc =
301+
let attr = createTemplate () in
302+
let newValueBinding =
303+
{valueDesc with pval_attributes = attr :: valueDesc.pval_attributes}
304+
in
305+
let signature_item_desc = Parsetree.Psig_value newValueBinding in
306+
Ast_helper.Sig.mk ~loc signature_item_desc
312307

313-
let processModDecl (modDecl : Parsetree.module_declaration) loc =
314-
let attr = createTemplate () in
315-
let newModDecl =
316-
{modDecl with pmd_attributes = attr :: modDecl.pmd_attributes}
317-
in
318-
Ast_helper.Sig.mk ~loc (Parsetree.Psig_module newModDecl)
308+
let processTypeDecl (typ : Parsetree.type_declaration) =
309+
let attr = createTemplate () in
310+
let newTypeDeclaration =
311+
{typ with ptype_attributes = attr :: typ.ptype_attributes}
312+
in
313+
newTypeDeclaration
319314

320-
let xform ~path ~pos ~codeActions ~signature ~printSignatureItem =
321-
let result = ref None in
322-
let iterator = mkIterator ~pos ~result in
323-
iterator.signature iterator signature;
324-
match !result with
325-
| Some (signatureItem, loc) -> (
326-
let newSignatureItem =
327-
match signatureItem with
328-
| Psig_value value_desc ->
329-
Some (processSigValue value_desc value_desc.pval_loc) (* Some loc *)
330-
| Psig_type (flag, hd :: tl) ->
331-
let newFirstTypeDecl = processTypeDecl hd in
332-
Some
333-
(Ast_helper.Sig.mk ~loc
334-
(Parsetree.Psig_type (flag, newFirstTypeDecl :: tl)))
335-
| Psig_module modDecl -> Some (processModDecl modDecl loc)
336-
| _ -> None
315+
let processModDecl (modDecl : Parsetree.module_declaration) loc =
316+
let attr = createTemplate () in
317+
let newModDecl =
318+
{modDecl with pmd_attributes = attr :: modDecl.pmd_attributes}
337319
in
320+
Ast_helper.Sig.mk ~loc (Parsetree.Psig_module newModDecl)
338321

339-
match newSignatureItem with
340-
| Some sig_item ->
341-
let range = rangeOfLoc sig_item.psig_loc in
342-
let newText = printSignatureItem ~range sig_item in
343-
let codeAction =
344-
CodeActions.make ~title:"Add Documentation template"
345-
~kind:RefactorRewrite ~uri:path ~newText ~range
322+
let xform ~path ~pos ~codeActions ~signature ~printSignatureItem =
323+
let result = ref None in
324+
let iterator = mkIterator ~pos ~result in
325+
iterator.signature iterator signature;
326+
match !result with
327+
| Some (signatureItem, loc) -> (
328+
let newSignatureItem =
329+
match signatureItem with
330+
| Psig_value value_desc ->
331+
Some (processSigValue value_desc value_desc.pval_loc) (* Some loc *)
332+
| Psig_type (flag, hd :: tl) ->
333+
let newFirstTypeDecl = processTypeDecl hd in
334+
Some
335+
(Ast_helper.Sig.mk ~loc
336+
(Parsetree.Psig_type (flag, newFirstTypeDecl :: tl)))
337+
| Psig_module modDecl -> Some (processModDecl modDecl loc)
338+
| _ -> None
346339
in
347-
codeActions := codeAction :: !codeActions
348-
| None -> ())
349-
| None -> ()
340+
341+
match newSignatureItem with
342+
| Some signatureItem ->
343+
let range = rangeOfLoc signatureItem.psig_loc in
344+
let newText = printSignatureItem ~range signatureItem in
345+
let codeAction =
346+
CodeActions.make ~title:"Add Documentation template"
347+
~kind:RefactorRewrite ~uri:path ~newText ~range
348+
in
349+
codeActions := codeAction :: !codeActions
350+
| None -> ())
351+
| None -> ()
352+
end
353+
354+
module Implementation = struct
355+
let mkIterator ~pos ~result =
356+
let structure_item (iterator : Ast_iterator.iterator)
357+
(si : Parsetree.structure_item) =
358+
match si.pstr_desc with
359+
| Pstr_value (_, {pvb_pat = {ppat_loc}; pvb_attributes} :: _) as r
360+
when Loc.hasPos ~pos ppat_loc
361+
&& ProcessAttributes.findDocAttribute pvb_attributes = None ->
362+
result := Some (r, si.pstr_loc)
363+
| Pstr_primitive value_description as r
364+
when Loc.hasPos ~pos value_description.pval_loc
365+
&& ProcessAttributes.findDocAttribute
366+
value_description.pval_attributes
367+
= None ->
368+
result := Some (r, si.pstr_loc)
369+
| Pstr_module {pmb_name = {loc}} as r ->
370+
if Loc.start loc = pos then result := Some (r, si.pstr_loc)
371+
else Ast_iterator.default_iterator.structure_item iterator si
372+
| Pstr_type (_, hd :: _) as r
373+
when Loc.hasPos ~pos hd.ptype_loc
374+
&& ProcessAttributes.findDocAttribute hd.ptype_attributes = None
375+
->
376+
result := Some (r, si.pstr_loc)
377+
| _ -> Ast_iterator.default_iterator.structure_item iterator si
378+
in
379+
{Ast_iterator.default_iterator with structure_item}
380+
381+
let processValueBinding (valueBinding : Parsetree.value_binding) =
382+
let attr = createTemplate () in
383+
let newValueBinding =
384+
{valueBinding with pvb_attributes = attr :: valueBinding.pvb_attributes}
385+
in
386+
newValueBinding
387+
388+
let processPrimitive (valueDesc : Parsetree.value_description) loc =
389+
let attr = createTemplate () in
390+
let newValueDesc =
391+
{valueDesc with pval_attributes = attr :: valueDesc.pval_attributes}
392+
in
393+
Ast_helper.Str.primitive ~loc newValueDesc
394+
395+
let processModuleBinding (modBind : Parsetree.module_binding) loc =
396+
let attr = createTemplate () in
397+
let newModBinding =
398+
{modBind with pmb_attributes = attr :: modBind.pmb_attributes}
399+
in
400+
Ast_helper.Str.module_ ~loc newModBinding
401+
402+
let xform ~pos ~codeActions ~path ~printStructureItem ~structure =
403+
let result = ref None in
404+
let iterator = mkIterator ~pos ~result in
405+
iterator.structure iterator structure;
406+
match !result with
407+
| None -> ()
408+
| Some (structureItem, loc) -> (
409+
let newStructureItem =
410+
match structureItem with
411+
| Pstr_value (flag, hd :: tl) ->
412+
let newValueBinding = processValueBinding hd in
413+
Some
414+
(Ast_helper.Str.mk ~loc
415+
(Parsetree.Pstr_value (flag, newValueBinding :: tl)))
416+
| Pstr_primitive valueDesc -> Some (processPrimitive valueDesc loc)
417+
| Pstr_module modBind -> Some (processModuleBinding modBind loc)
418+
| Pstr_type (flag, hd :: tl) ->
419+
let newFirstTypeDecl = Interface.processTypeDecl hd in
420+
Some
421+
(Ast_helper.Str.mk ~loc
422+
(Parsetree.Pstr_type (flag, newFirstTypeDecl :: tl)))
423+
| _ -> None
424+
in
425+
426+
match newStructureItem with
427+
| Some structureItem ->
428+
let range = rangeOfLoc structureItem.pstr_loc in
429+
let newText = printStructureItem ~range structureItem in
430+
let codeAction =
431+
CodeActions.make ~title:"Add Documentation template"
432+
~kind:RefactorRewrite ~uri:path ~newText ~range
433+
in
434+
codeActions := codeAction :: !codeActions
435+
| None -> ())
436+
end
350437
end
351438

352-
let parse ~filename =
439+
let parseImplementation ~filename =
353440
let {Res_driver.parsetree = structure; comments} =
354441
Res_driver.parsingEngine.parseImplementation ~forPrinter:false ~filename
355442
in
@@ -399,19 +486,29 @@ let parseInterface ~filename =
399486
(structure, printSignatureItem)
400487

401488
let extractCodeActions ~path ~pos ~currentFile ~debug =
402-
match Cmt.loadFullCmtFromPath ~path with
403-
| Some full when Files.classifySourceFile currentFile = Res ->
489+
let codeActions = ref [] in
490+
match Files.classifySourceFile currentFile with
491+
| Res ->
404492
let structure, printExpr, printStructureItem =
405-
parse ~filename:currentFile
493+
parseImplementation ~filename:currentFile
406494
in
407-
let codeActions = ref [] in
408-
AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions ~debug;
409495
IfThenElse.xform ~pos ~codeActions ~printExpr ~path structure;
410496
AddBracesToFn.xform ~pos ~codeActions ~path ~printStructureItem structure;
497+
AddDocTemplate.Implementation.xform ~pos ~codeActions ~path
498+
~printStructureItem ~structure;
499+
500+
(* This Code Action needs type info *)
501+
let () =
502+
match Cmt.loadFullCmtFromPath ~path with
503+
| Some full ->
504+
AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions ~debug
505+
| None -> ()
506+
in
507+
411508
!codeActions
412-
| _ when Files.classifySourceFile currentFile = Resi ->
509+
| Resi ->
413510
let signature, printSignatureItem = parseInterface ~filename:currentFile in
414-
let codeActions = ref [] in
415-
AddDocTemplate.xform ~pos ~codeActions ~path ~signature ~printSignatureItem;
511+
AddDocTemplate.Interface.xform ~pos ~codeActions ~path ~signature
512+
~printSignatureItem;
416513
!codeActions
417-
| _ -> []
514+
| Other -> []

Diff for: analysis/tests/not_compiled/DocTemplate.res

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
type a = {a: int}
2+
// ^xfm
3+
4+
type rec t = A | B
5+
// ^xfm
6+
and e = C
7+
@unboxed type name = Name(string)
8+
// ^xfm
9+
let a = 1
10+
// ^xfm
11+
let inc = x => x + 1
12+
// ^xfm
13+
module T = {
14+
// ^xfm
15+
let b = 1
16+
// ^xfm
17+
}
18+
@module("path")
19+
external dirname: string => string = "dirname"
20+
//^xfm
+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
Xform not_compiled/DocTemplate.res 3:3
2+
can't find module DocTemplate
3+
Hit: Add Documentation template
4+
{"start": {"line": 3, "character": 0}, "end": {"line": 5, "character": 9}}
5+
newText:
6+
<--here
7+
/**
8+
9+
*/
10+
type rec t = A | B
11+
// ^xfm
12+
and e = C
13+
14+
Xform not_compiled/DocTemplate.res 6:15
15+
can't find module DocTemplate
16+
Hit: Add Documentation template
17+
{"start": {"line": 6, "character": 0}, "end": {"line": 6, "character": 33}}
18+
newText:
19+
<--here
20+
/**
21+
22+
*/
23+
@unboxed
24+
type name = Name(string)
25+
26+
Xform not_compiled/DocTemplate.res 8:4
27+
can't find module DocTemplate
28+
Hit: Add Documentation template
29+
{"start": {"line": 8, "character": 0}, "end": {"line": 8, "character": 9}}
30+
newText:
31+
<--here
32+
/**
33+
34+
*/
35+
let a = 1
36+
37+
Xform not_compiled/DocTemplate.res 10:4
38+
can't find module DocTemplate
39+
Hit: Add Documentation template
40+
{"start": {"line": 10, "character": 0}, "end": {"line": 10, "character": 20}}
41+
newText:
42+
<--here
43+
/**
44+
45+
*/
46+
let inc = x => x + 1
47+
48+
Xform not_compiled/DocTemplate.res 12:7
49+
can't find module DocTemplate
50+
Hit: Add Documentation template
51+
{"start": {"line": 12, "character": 0}, "end": {"line": 16, "character": 1}}
52+
newText:
53+
<--here
54+
/**
55+
56+
*/
57+
module T = {
58+
// ^xfm
59+
let b = 1
60+
// ^xfm
61+
}
62+
63+
Xform not_compiled/DocTemplate.res 14:6
64+
can't find module DocTemplate
65+
Hit: Add Documentation template
66+
{"start": {"line": 14, "character": 2}, "end": {"line": 14, "character": 11}}
67+
newText:
68+
<--here
69+
/**
70+
71+
*/
72+
let b = 1
73+
74+
Xform not_compiled/DocTemplate.res 18:2
75+
can't find module DocTemplate
76+
Hit: Add Documentation template
77+
{"start": {"line": 17, "character": 0}, "end": {"line": 18, "character": 46}}
78+
newText:
79+
<--here
80+
/**
81+
82+
*/
83+
@module("path")
84+
external dirname: string => string = "dirname"
85+

0 commit comments

Comments
 (0)