Skip to content

Commit 0173421

Browse files
authored
Enhance decorator completion (#908)
* enhance decorator completion * changelog
1 parent a83177c commit 0173421

8 files changed

+295
-63
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
1313
## master
1414

15+
#### :nail_care: Polish
16+
17+
Enhance decorator completion. https://github.com/rescript-lang/rescript-vscode/pull/908
18+
1519
## 1.38.0
1620

1721
#### :nail_care: Polish

analysis/src/CompletionBackEnd.ml

+40-5
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,36 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
17461746
&& (forHover || not (List.mem name identsSeen)))
17471747
|> List.map mkLabel)
17481748
@ keyLabels
1749+
| CdecoratorPayload (JsxConfig {prefix; nested}) -> (
1750+
let mkField ~name ~primitive =
1751+
{
1752+
stamp = -1;
1753+
fname = {loc = Location.none; txt = name};
1754+
optional = true;
1755+
typ = Ctype.newconstr (Path.Pident (Ident.create primitive)) [];
1756+
docstring = [];
1757+
deprecated = None;
1758+
}
1759+
in
1760+
let typ : completionType =
1761+
Trecord
1762+
{
1763+
env;
1764+
definition = `NameOnly "jsxConfig";
1765+
fields =
1766+
[
1767+
mkField ~name:"version" ~primitive:"int";
1768+
mkField ~name:"module_" ~primitive:"string";
1769+
mkField ~name:"mode" ~primitive:"string";
1770+
];
1771+
}
1772+
in
1773+
match typ |> TypeUtils.resolveNested ~env ~full ~nested with
1774+
| None -> []
1775+
| Some (typ, _env, completionContext, typeArgContext) ->
1776+
typ
1777+
|> completeTypedValue ?typeArgContext ~rawOpens ~mode:Expression ~full
1778+
~prefix ~completionContext)
17491779
| CdecoratorPayload (Module prefix) ->
17501780
let packageJsonPath =
17511781
Utils.findPackageJson (full.package.rootPath |> Uri.fromPath)
@@ -1824,8 +1854,13 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
18241854
~kind:(Label (if isLocal then "Local file" else "Package"))
18251855
~env)
18261856
| Cdecorator prefix ->
1827-
let mkDecorator (name, docstring) =
1828-
{(Completion.create name ~kind:(Label "") ~env) with docstring}
1857+
let mkDecorator (name, docstring, maybeInsertText) =
1858+
{
1859+
(Completion.createWithSnippet ~name ~kind:(Label "") ~env
1860+
?insertText:maybeInsertText ())
1861+
with
1862+
docstring;
1863+
}
18291864
in
18301865
let isTopLevel = String.starts_with ~prefix:"@" prefix in
18311866
let prefix =
@@ -1837,16 +1872,16 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
18371872
else CompletionDecorators.local
18381873
in
18391874
decorators
1840-
|> List.filter (fun (decorator, _) -> Utils.startsWith decorator prefix)
1841-
|> List.map (fun (decorator, doc) ->
1875+
|> List.filter (fun (decorator, _, _) -> Utils.startsWith decorator prefix)
1876+
|> List.map (fun (decorator, maybeInsertText, doc) ->
18421877
let parts = String.split_on_char '.' prefix in
18431878
let len = String.length prefix in
18441879
let dec2 =
18451880
if List.length parts > 1 then
18461881
String.sub decorator len (String.length decorator - len)
18471882
else decorator
18481883
in
1849-
(dec2, doc))
1884+
(dec2, doc, maybeInsertText))
18501885
|> List.map mkDecorator
18511886
| CnamedArg (cp, prefix, identsSeen) ->
18521887
let labels =

analysis/src/CompletionDecorators.ml

+42
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
let local =
22
[
33
( "as",
4+
Some "as(\"$0\")",
45
[
56
{|The `@as` decorator is commonly used on record types to alias record field names to a different JavaScript attribute name.
67

@@ -11,6 +12,7 @@ It is also possible to map a ReScript record to a JavaScript array by passing in
1112
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#as-decorator).|};
1213
] );
1314
( "dead",
15+
None,
1416
[
1517
{|The `@dead` decorator is for reanalyze, a static analysis tool for ReScript that can do dead code analysis.
1618

@@ -21,12 +23,14 @@ It is also possible to map a ReScript record to a JavaScript array by passing in
2123
> Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|};
2224
] );
2325
( "deriving",
26+
Some "deriving($0)",
2427
[
2528
{|When the `@deriving` decorator is applied to a record type, it expands the type into a factory function plus a set of getter/setter functions for its fields.
2629

2730
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#deriving-decorator).|};
2831
] );
2932
( "deprecated",
33+
Some "deprecated(\"$0\")",
3034
[
3135
{|The `@deprecated` decorator is used to add deprecation notes to types, values and submodules. The compiler and editor tooling will yield a warning whenever a deprecated entity is being used.
3236

@@ -35,6 +39,7 @@ Alternatively, use the `@@deprecated` decorator to add a deprecation warning to
3539
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#expression-deprecated-decorator).|};
3640
] );
3741
( "doesNotRaise",
42+
None,
3843
[
3944
{|The `@doesNotRaise` decorator is for reanalyze, a static analysis tool for ReScript that can perform exception analysis.
4045

@@ -46,54 +51,63 @@ could potentially raise.
4651
> Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|};
4752
] );
4853
( "genType",
54+
None,
4955
[
5056
{|The @genType decorator may be used to export ReScript values and types to JavaScript, and import JavaScript values and types into ReScript. It allows seamless integration of compiled ReScript modules in existing TypeScript, Flow, or plain JavaScript codebases, without loosing type information across different type systems.
5157

5258
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#gentype-decorator).|};
5359
] );
5460
( "genType.as",
61+
Some "genType.as(\"$0\")",
5562
[
5663
{|The @genType decorator may be used to export ReScript values and types to JavaScript, and import JavaScript values and types into ReScript. It allows seamless integration of compiled ReScript modules in existing TypeScript, Flow, or plain JavaScript codebases, without loosing type information across different type systems.
5764

5865
[Read more and see examples in the documentation](https://rescript-lang.org/docs/gentype/latest/usage).|};
5966
] );
6067
( "genType.import",
68+
None,
6169
[
6270
{|The @genType decorator may be used to export ReScript values and types to JavaScript, and import JavaScript values and types into ReScript. It allows seamless integration of compiled ReScript modules in existing TypeScript, Flow, or plain JavaScript codebases, without loosing type information across different type systems.
6371

6472
[Read more and see examples in the documentation](https://rescript-lang.org/docs/gentype/latest/usage).|};
6573
] );
6674
( "genType.opaque",
75+
None,
6776
[
6877
{|The @genType decorator may be used to export ReScript values and types to JavaScript, and import JavaScript values and types into ReScript. It allows seamless integration of compiled ReScript modules in existing TypeScript, Flow, or plain JavaScript codebases, without loosing type information across different type systems.
6978

7079
[Read more and see examples in the documentation](https://rescript-lang.org/docs/gentype/latest/usage).|};
7180
] );
7281
( "get",
82+
None,
7383
[
7484
{|The `@get` decorator is used to bind to a property of an object.
7585

7686
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#get-decorator).|};
7787
] );
7888
( "get_index",
89+
None,
7990
[
8091
{|The `@get_index` decorator is used to access a dynamic property on an object, or an index of an array.
8192

8293
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#get-index-decorator).|};
8394
] );
8495
( "inline",
96+
None,
8597
[
8698
{|The `@inline` decorator tells the compiler to inline its value in every place the binding is being used, rather than use a variable.
8799

88100
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#inline-decorator).|};
89101
] );
90102
( "int",
103+
None,
91104
[
92105
{|The `@int` decorator can be used with polymorphic variants and the @as decorator on externals to modify the compiled JavaScript to use integers for the values instead of strings.
93106

94107
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#int-decorator).|};
95108
] );
96109
( "live",
110+
None,
97111
[
98112
{|The `@live` decorator is for reanalyze, a static analysis tool for ReScript that can do dead code analysis.
99113

@@ -104,31 +118,36 @@ could potentially raise.
104118
Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|};
105119
] );
106120
( "meth",
121+
None,
107122
[
108123
{|The `@meth` decorator is used to call a function on a JavaScript object, and avoid issues with currying.
109124

110125
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#meth-decorator).|};
111126
] );
112127
( "module",
128+
Some "module(\"$0\")",
113129
[
114130
{|The `@module` decorator is used to bind to a JavaScript module.
115131

116132
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#module-decorator).|};
117133
] );
118134
( "new",
135+
None,
119136
[
120137
{|
121138
The `@new` decorator is used whenever you need to bind to a JavaScript class constructor that requires the new keword for instantiation.|
122139

123140
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#new-decorator).|};
124141
] );
125142
( "obj",
143+
None,
126144
[
127145
{|The `@obj` decorator is used to create functions that return JavaScript objects with properties that match the function's parameter labels.
128146

129147
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#obj-decorator).|};
130148
] );
131149
( "raises",
150+
Some "raises(\"$0\")",
132151
[
133152
{|The `@raises` decorator is for reanalyze, a static analysis tool for ReScript that can perform exception analysis.
134153

@@ -139,6 +158,7 @@ Example `@raises(Exn)` or `@raises([E1, E2, E3])` for multiple exceptions.
139158
> Hint: Did you know you can run an interactive code analysis in your project by running the command `> ReScript: Start Code Analyzer`? Try it!|};
140159
] );
141160
( "react.component",
161+
None,
142162
[
143163
{|The `@react.component` decorator is used to annotate functions that are RescriptReact components.
144164

@@ -149,72 +169,84 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i
149169
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#react-component-decorator).|};
150170
] );
151171
( "return",
172+
Some "return(${1:nullable})",
152173
[
153174
{|The `@return` decorator is used to control how `null` and `undefined` values are converted to option types in ReScript.
154175

155176
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#return-decorator).|};
156177
] );
157178
( "scope",
179+
Some "scope(\"$0\")",
158180
[
159181
{|The `@scope` decorator is used with other decorators such as `@val` and `@module` to declare a parent scope for the binding.
160182

161183
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#scope-decorator).|};
162184
] );
163185
( "send",
186+
None,
164187
[
165188
{|The `@send` decorator is used to bind to a method on an object or array.
166189

167190
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#send-decorator).|};
168191
] );
169192
( "set",
193+
None,
170194
[
171195
{|The `@set` decorator is used to set a property of an object.
172196

173197
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#set-decorator).|};
174198
] );
175199
( "set_index",
200+
None,
176201
[
177202
{|The `@set_index` decorator is used to set a dynamic property on an object, or an index of an array.
178203

179204
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#set-index-decorator).|};
180205
] );
181206
( "string",
207+
None,
182208
[
183209
{|The `@string` decorator can be used with polymorphic variants and the `@as` decorator on externals to modify the string values used for the variants in the compiled JavaScript.
184210

185211
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#string-decorator).|};
186212
] );
187213
( "this",
214+
None,
188215
[
189216
{|The `@this` decorator may be used to bind to an external callback function that require access to a this context.
190217

191218
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#this-decorator).|};
192219
] );
193220
( "unboxed",
221+
None,
194222
[
195223
{|The `@unboxed` decorator provides a way to unwrap variant constructors that have a single argument, or record objects that have a single field.
196224

197225
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#unboxed-decorator).|};
198226
] );
199227
( "uncurry",
228+
None,
200229
[
201230
{|The `@uncurry` decorator can be used to mark any callback argument within an external function as an uncurried function without the need for any explicit uncurried function syntax (`(.) => { ... }`).
202231

203232
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#uncurry-decorator).|};
204233
] );
205234
( "unwrap",
235+
None,
206236
[
207237
{|The `@unwrap` decorator may be used when binding to external functions that accept multiple types for an argument.
208238

209239
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#unwrap-decorator).|};
210240
] );
211241
( "val",
242+
None,
212243
[
213244
{|The `@val` decorator allows you to bind to JavaScript values that are on the global scope.
214245

215246
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#val-decorator).|};
216247
] );
217248
( "variadic",
249+
None,
218250
[
219251
{|The `@variadic` decorator is used to model JavaScript functions that take a variable number of arguments, where all arguments are of the same type.
220252

@@ -225,22 +257,32 @@ Note: The `@react.component` decorator requires the react-jsx config to be set i
225257
let toplevel =
226258
[
227259
( "deprecated",
260+
Some "deprecated(\"$0\")",
228261
[
229262
{|The `@@deprecated` decorator is used to add a deprecation note to the file-level of a module. The compiler and editor tooling will yield a warning whenever a deprecated file module is being used.
230263

231264
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#module-deprecated-decorator).|};
232265
] );
233266
( "directive",
267+
Some "directive(\"$0\")",
234268
[
235269
{|The `@@directive` decorator will output that string verbatim at the very top of the generated JavaScript file, before any imports.
236270

237271
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#directive-decorator).|};
238272
] );
239273
( "warning",
274+
Some "warning(\"$0\")",
240275
[
241276
{|The `@@warning` decorator is used to modify the enabled compiler warnings for the current module. See here for all available warning numbers.
242277

243278
[Read more and see examples in the documentation](https://rescript-lang.org/syntax-lookup#module-warning-decorator).
244279
|};
245280
] );
281+
( "jsxConfig",
282+
Some "jsxConfig({$0})",
283+
[
284+
{|The `@@jsxConfig` decorator is used to change the config for JSX on the fly.
285+
286+
[Read more and see examples in the documentation](https://rescript-lang.org/docs/manual/latest/jsx#file-level-configuration).|};
287+
] );
246288
]

0 commit comments

Comments
 (0)