Skip to content

Commit 81779fd

Browse files
committed
bootstrap ReScript MCP + add a first command
1 parent f4f7296 commit 81779fd

File tree

19 files changed

+1681
-8
lines changed

19 files changed

+1681
-8
lines changed

analysis/bin/main.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ let main () =
110110
path line col
111111
in
112112
match args with
113+
| [_; "mcp"; "loc-info"; path; line; col] ->
114+
Mcp.LocInfo.locInfo ~path ~pos:(int_of_string line, int_of_string col)
115+
|> print_endline
113116
| [_; "cache-project"; rootPath] -> (
114117
Cfg.readProjectConfigCache := false;
115118
let uri = Uri.fromPath rootPath in

analysis/src/Commands.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,13 @@ let test ~path =
432432
("TypeDefinition " ^ path ^ " " ^ string_of_int line ^ ":"
433433
^ string_of_int col);
434434
typeDefinition ~path ~pos:(line, col) ~debug:true
435+
| "mli" ->
436+
print_endline
437+
("MCP loc info " ^ path ^ " " ^ string_of_int line ^ ":"
438+
^ string_of_int col);
439+
let currentFile = createCurrentFile () in
440+
Mcp.LocInfo.locInfo ~path ~pos:(line, col) |> print_endline;
441+
Sys.remove currentFile
435442
| "xfm" ->
436443
let currentFile = createCurrentFile () in
437444
(* +2 is to ensure that the character ^ points to is what's considered the end of the selection. *)

analysis/src/Hover.ml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,12 @@ let expandTypes ~file ~package ~supportsMarkdownLinks typ =
118118
`InlineType )
119119
| all ->
120120
let typesSeen = ref StringSet.empty in
121-
let typeId ~(env : QueryEnv.t) ~name =
122-
env.file.moduleName :: List.rev (name :: env.pathRev) |> String.concat "."
123-
in
124121
( all
125122
(* Don't produce duplicate type definitions for recursive types *)
126-
|> List.filter (fun {env; name} ->
127-
let typeId = typeId ~env ~name in
123+
|> List.filter (fun {env; name; loc} ->
124+
let typeId =
125+
TypeUtils.typeId ~env ~name:(Location.mkloc name loc)
126+
in
128127
if StringSet.mem typeId !typesSeen then false
129128
else (
130129
typesSeen := StringSet.add typeId !typesSeen;

analysis/src/Mcp.ml

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
open SharedTypes
2+
3+
module StringSet = Set.Make (String)
4+
5+
module Utils = struct
6+
let wrapInTag content ~tag = Printf.sprintf "<%s>\n%s\n</%s>" tag content tag
7+
let wrapInTagOpt content ~tag =
8+
match content with
9+
| None -> None
10+
| Some content -> Some (wrapInTag content ~tag)
11+
end
12+
13+
module LocInfo = struct
14+
let showModule = Hover.showModule
15+
16+
(* LocInfo thoughts:
17+
- Check for long variants and/or records, and do not expand them automatically. DomProps being one example. *)
18+
19+
let locInfo ~path ~pos =
20+
let debug = false in
21+
let result =
22+
match Cmt.loadFullCmtFromPath ~path with
23+
| None -> None
24+
| Some full -> (
25+
match References.getLocItem ~full ~pos ~debug with
26+
| None -> None
27+
| Some locItem -> (
28+
let isModule =
29+
match locItem.locType with
30+
| LModule _ | TopLevelModule _ -> true
31+
| TypeDefinition _ | Typed _ | Constant _ -> false
32+
in
33+
let uriLocOpt = References.definitionForLocItem ~full locItem in
34+
let skipZero =
35+
match uriLocOpt with
36+
| None -> false
37+
| Some (_, loc) ->
38+
let isInterface = full.file.uri |> Uri.isInterface in
39+
let posIsZero {Lexing.pos_lnum; pos_bol; pos_cnum} =
40+
(not isInterface) && pos_lnum = 1 && pos_cnum - pos_bol = 0
41+
in
42+
(* Skip if range is all zero, unless it's a module *)
43+
(not isModule) && posIsZero loc.loc_start && posIsZero loc.loc_end
44+
in
45+
if skipZero then None
46+
else
47+
let file = full.file in
48+
let package = full.package in
49+
match locItem.locType with
50+
| TypeDefinition
51+
(name, ({type_manifest = Some tmanifest} as decl), _stamp) ->
52+
Some
53+
(Shared.declToString name decl
54+
^ "\n\n"
55+
^ Shared.typeToString tmanifest)
56+
| TypeDefinition (name, decl, _stamp) ->
57+
Some (Shared.declToString name decl)
58+
| LModule (Definition (stamp, _tip))
59+
| LModule (LocalReference (stamp, _tip)) -> (
60+
match Stamps.findModule file.stamps stamp with
61+
| None -> None
62+
| Some md -> (
63+
match References.resolveModuleReference ~file ~package md with
64+
| None -> None
65+
| Some (file, declared) ->
66+
let name, docstring =
67+
match declared with
68+
| Some d -> (d.name.txt, d.docstring)
69+
| None -> (file.moduleName, file.structure.docstring)
70+
in
71+
showModule ~docstring ~name ~file declared ~package))
72+
| LModule (GlobalReference (moduleName, path, tip)) -> (
73+
match ProcessCmt.fileForModule ~package moduleName with
74+
| None -> None
75+
| Some file -> (
76+
let env = QueryEnv.fromFile file in
77+
match References.exportedForTip ~env ~path ~package ~tip with
78+
| None -> None
79+
| Some (_env, _name, stamp) -> (
80+
match Stamps.findModule file.stamps stamp with
81+
| None -> None
82+
| Some md -> (
83+
match
84+
References.resolveModuleReference ~file ~package md
85+
with
86+
| None -> None
87+
| Some (file, declared) ->
88+
let name, docstring =
89+
match declared with
90+
| Some d -> (d.name.txt, d.docstring)
91+
| None -> (file.moduleName, file.structure.docstring)
92+
in
93+
showModule ~docstring ~name ~file ~package declared))))
94+
| LModule NotFound -> None
95+
| TopLevelModule name -> (
96+
match ProcessCmt.fileForModule ~package name with
97+
| None -> None
98+
| Some file ->
99+
showModule ~docstring:file.structure.docstring
100+
~name:file.moduleName ~file ~package None)
101+
| Typed (name, t, _) ->
102+
let {TypeUtils.ExpandType.mainTypes; relatedTypes} =
103+
TypeUtils.ExpandType.expandTypes
104+
(TypeUtils.ExpandType.TypeExpr
105+
{
106+
typeExpr = t;
107+
name = Some (Location.mkloc name locItem.loc);
108+
env = QueryEnv.fromFile full.file;
109+
})
110+
~full
111+
in
112+
Some
113+
(Printf.sprintf
114+
"<main_types>\n\
115+
%s\n\
116+
</main_types>\n\n\
117+
<related_types>\n\
118+
%s\n\
119+
</related_types>"
120+
(mainTypes
121+
|> List.map
122+
(fun (input : TypeUtils.ExpandType.expandTypeInput) ->
123+
match input with
124+
| TypeUtils.ExpandType.TypeExpr {typeExpr} ->
125+
Shared.typeToString typeExpr
126+
| TypeUtils.ExpandType.TypeDecl {name; typeDecl} ->
127+
Shared.declToString name.txt typeDecl)
128+
|> String.concat "\n\n")
129+
(relatedTypes
130+
|> List.map
131+
(fun (input : TypeUtils.ExpandType.expandTypeInput) ->
132+
match input with
133+
| TypeUtils.ExpandType.TypeExpr {typeExpr} ->
134+
Shared.typeToString typeExpr
135+
| TypeUtils.ExpandType.TypeDecl {name; typeDecl} ->
136+
Shared.declToString name.txt typeDecl)
137+
|> String.concat "\n\n"))
138+
| Constant t ->
139+
Some
140+
(match t with
141+
| Const_int _ -> "int"
142+
| Const_char _ -> "char"
143+
| Const_string _ -> "string"
144+
| Const_float _ -> "float"
145+
| Const_int32 _ -> "int32"
146+
| Const_int64 _ -> "int64"
147+
| Const_bigint _ -> "bigint")))
148+
in
149+
match result with
150+
| None -> "No result."
151+
| Some s -> s
152+
end

0 commit comments

Comments
 (0)