@@ -27,8 +27,11 @@ use noirc_frontend::hir::FunctionNameMatch;
27
27
use serde_json:: Value as JsonValue ;
28
28
use tower:: Service ;
29
29
30
+ const ARROW : & str = "▶\u{fe0e} " ;
30
31
const TEST_COMMAND : & str = "nargo.test" ;
31
- const TEST_CODELENS_TITLE : & str = "▶\u{fe0e} Run Test" ;
32
+ const TEST_CODELENS_TITLE : & str = "Run Test" ;
33
+ const COMPILE_COMMAND : & str = "nargo.compile" ;
34
+ const COMPILE_CODELENS_TITLE : & str = "Compile" ;
32
35
33
36
// State for the LSP gets implemented on this struct and is internal to the implementation
34
37
pub struct LspState {
@@ -185,7 +188,7 @@ fn on_code_lens_request(
185
188
186
189
for package in & workspace {
187
190
let ( mut context, crate_id) = prepare_package ( package) ;
188
- // We ignore the warnings and errors produced by compilation for producing codelenses
191
+ // We ignore the warnings and errors produced by compilation for producing code lenses
189
192
// because we can still get the test functions even if compilation fails
190
193
let _ = check_crate ( & mut context, crate_id, false ) ;
191
194
@@ -210,7 +213,7 @@ fn on_code_lens_request(
210
213
. unwrap_or_default ( ) ;
211
214
212
215
let command = Command {
213
- title : TEST_CODELENS_TITLE . into ( ) ,
216
+ title : format ! ( "{ARROW} {TEST_CODELENS_TITLE}" ) ,
214
217
command : TEST_COMMAND . into ( ) ,
215
218
arguments : Some ( vec ! [
216
219
"--program-dir" . into( ) ,
@@ -226,6 +229,73 @@ fn on_code_lens_request(
226
229
227
230
lenses. push ( lens) ;
228
231
}
232
+
233
+ if package. is_binary ( ) {
234
+ if let Some ( main_func_id) = context. get_main_function ( & crate_id) {
235
+ let location = context. function_meta ( & main_func_id) . name . location ;
236
+ let file_id = location. file ;
237
+
238
+ // Ignore diagnostics for any file that wasn't the file we saved
239
+ // TODO: In the future, we could create "related" diagnostics for these files
240
+ // TODO: This currently just appends the `.nr` file extension that we store as a constant,
241
+ // but that won't work if we accept other extensions
242
+ if fm. path ( file_id) . with_extension ( FILE_EXTENSION ) != file_path {
243
+ continue ;
244
+ }
245
+
246
+ let range = byte_span_to_range ( files, file_id. as_usize ( ) , location. span . into ( ) )
247
+ . unwrap_or_default ( ) ;
248
+
249
+ let command = Command {
250
+ title : format ! ( "{ARROW} {COMPILE_CODELENS_TITLE}" ) ,
251
+ command : COMPILE_COMMAND . into ( ) ,
252
+ arguments : Some ( vec ! [
253
+ "--program-dir" . into( ) ,
254
+ format!( "{}" , workspace. root_dir. display( ) ) . into( ) ,
255
+ "--package" . into( ) ,
256
+ format!( "{}" , package. name) . into( ) ,
257
+ ] ) ,
258
+ } ;
259
+
260
+ let lens = CodeLens { range, command : command. into ( ) , data : None } ;
261
+
262
+ lenses. push ( lens) ;
263
+ }
264
+ }
265
+
266
+ if package. is_contract ( ) {
267
+ // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying
268
+ for contract in context. get_all_contracts ( & crate_id) {
269
+ let location = contract. location ;
270
+ let file_id = location. file ;
271
+
272
+ // Ignore diagnostics for any file that wasn't the file we saved
273
+ // TODO: In the future, we could create "related" diagnostics for these files
274
+ // TODO: This currently just appends the `.nr` file extension that we store as a constant,
275
+ // but that won't work if we accept other extensions
276
+ if fm. path ( file_id) . with_extension ( FILE_EXTENSION ) != file_path {
277
+ continue ;
278
+ }
279
+
280
+ let range = byte_span_to_range ( files, file_id. as_usize ( ) , location. span . into ( ) )
281
+ . unwrap_or_default ( ) ;
282
+
283
+ let command = Command {
284
+ title : format ! ( "{ARROW} {COMPILE_CODELENS_TITLE}" ) ,
285
+ command : COMPILE_COMMAND . into ( ) ,
286
+ arguments : Some ( vec ! [
287
+ "--program-dir" . into( ) ,
288
+ format!( "{}" , workspace. root_dir. display( ) ) . into( ) ,
289
+ "--package" . into( ) ,
290
+ format!( "{}" , package. name) . into( ) ,
291
+ ] ) ,
292
+ } ;
293
+
294
+ let lens = CodeLens { range, command : command. into ( ) , data : None } ;
295
+
296
+ lenses. push ( lens) ;
297
+ }
298
+ }
229
299
}
230
300
231
301
let res = if lenses. is_empty ( ) { Ok ( None ) } else { Ok ( Some ( lenses) ) } ;
@@ -365,6 +435,9 @@ fn on_did_save_text_document(
365
435
}
366
436
}
367
437
438
+ // We need to refresh lenses when we compile since that's the only time they can be accurately reflected
439
+ let _ = state. client . code_lens_refresh ( ( ) ) ;
440
+
368
441
let _ = state. client . publish_diagnostics ( PublishDiagnosticsParams {
369
442
uri : params. text_document . uri ,
370
443
version : None ,
0 commit comments