diff --git a/crates/lsp/src/lib.rs b/crates/lsp/src/lib.rs index 70ffdbdec4..d8b572db34 100644 --- a/crates/lsp/src/lib.rs +++ b/crates/lsp/src/lib.rs @@ -32,6 +32,8 @@ const TEST_COMMAND: &str = "nargo.test"; const TEST_CODELENS_TITLE: &str = "Run Test"; const COMPILE_COMMAND: &str = "nargo.compile"; const COMPILE_CODELENS_TITLE: &str = "Compile"; +const EXECUTE_COMMAND: &str = "nargo.execute"; +const EXECUTE_CODELENS_TITLE: &str = "Execute"; // State for the LSP gets implemented on this struct and is internal to the implementation pub struct LspState { @@ -212,7 +214,7 @@ fn on_code_lens_request( let range = byte_span_to_range(files, file_id.as_usize(), location.span.into()) .unwrap_or_default(); - let command = Command { + let test_command = Command { title: format!("{ARROW} {TEST_CODELENS_TITLE}"), command: TEST_COMMAND.into(), arguments: Some(vec![ @@ -225,9 +227,91 @@ fn on_code_lens_request( ]), }; - let lens = CodeLens { range, command: command.into(), data: None }; + let test_lens = CodeLens { range, command: Some(test_command), data: None }; - lenses.push(lens); + lenses.push(test_lens); + } + + if package.is_binary() { + if let Some(main_func_id) = context.get_main_function(&crate_id) { + let location = context.function_meta(&main_func_id).name.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + // TODO: This currently just appends the `.nr` file extension that we store as a constant, + // but that won't work if we accept other extensions + if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path { + continue; + } + + let range = byte_span_to_range(files, file_id.as_usize(), location.span.into()) + .unwrap_or_default(); + + let compile_command = Command { + title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"), + command: COMPILE_COMMAND.into(), + arguments: Some(vec![ + "--program-dir".into(), + format!("{}", workspace.root_dir.display()).into(), + "--package".into(), + format!("{}", package.name).into(), + ]), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + + let execute_command = Command { + title: EXECUTE_CODELENS_TITLE.to_string(), + command: EXECUTE_COMMAND.into(), + arguments: Some(vec![ + "--program-dir".into(), + format!("{}", workspace.root_dir.display()).into(), + "--package".into(), + format!("{}", package.name).into(), + ]), + }; + + let execute_lens = CodeLens { range, command: Some(execute_command), data: None }; + + lenses.push(execute_lens); + } + } + + if package.is_contract() { + // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying + for contract in context.get_all_contracts(&crate_id) { + let location = contract.location; + let file_id = location.file; + + // Ignore diagnostics for any file that wasn't the file we saved + // TODO: In the future, we could create "related" diagnostics for these files + // TODO: This currently just appends the `.nr` file extension that we store as a constant, + // but that won't work if we accept other extensions + if fm.path(file_id).with_extension(FILE_EXTENSION) != file_path { + continue; + } + + let range = byte_span_to_range(files, file_id.as_usize(), location.span.into()) + .unwrap_or_default(); + + let compile_command = Command { + title: format!("{ARROW} {COMPILE_CODELENS_TITLE}"), + command: COMPILE_COMMAND.into(), + arguments: Some(vec![ + "--program-dir".into(), + format!("{}", workspace.root_dir.display()).into(), + "--package".into(), + format!("{}", package.name).into(), + ]), + }; + + let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; + + lenses.push(compile_lens); + } } if package.is_binary() {