diff --git a/Cargo.lock b/Cargo.lock index a9c9ca4992..c0a8bab642 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3202,13 +3202,14 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550446e84739dcaf6d48a4a093973850669e13e8a34d8f8d64851041be267cd9" +checksum = "9462c4dc73e17f971ec1f171d44bfffb72e65a130117233388a0ebc7ec5656f9" dependencies = [ "crossbeam-channel", "log", "serde", + "serde_derive", "serde_json", ] diff --git a/Cargo.toml b/Cargo.toml index 18042e20a4..c4c2b03237 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ libproc = "0.14" log = "0.4" lru = "0.12" lscolors = { version = "0.17", default-features = false } -lsp-server = "0.7.5" +lsp-server = "0.7.8" lsp-types = { version = "0.97.0", features = ["proposed"] } lsp-textdocument = "0.4.0" mach2 = "0.4" diff --git a/crates/nu-lsp/src/ast.rs b/crates/nu-lsp/src/ast.rs index bee0c007f3..d8b1a9acfc 100644 --- a/crates/nu-lsp/src/ast.rs +++ b/crates/nu-lsp/src/ast.rs @@ -198,7 +198,7 @@ fn try_find_id_in_def( id_ref: Option<&Id>, ) -> Option<(Id, Span)> { let call_name = working_set.get_span_contents(call.head); - if call_name != "def".as_bytes() && call_name != "export def".as_bytes() { + if call_name != b"def" && call_name != b"export def" { return None; }; let mut span = None; diff --git a/crates/nu-lsp/src/workspace.rs b/crates/nu-lsp/src/workspace.rs index 37eb81182c..979f09a42b 100644 --- a/crates/nu-lsp/src/workspace.rs +++ b/crates/nu-lsp/src/workspace.rs @@ -54,37 +54,18 @@ fn find_reference_in_file( file: &FullTextDocument, fp: &Path, id: &Id, -) -> Option> { - let fp_str = fp.to_str()?; +) -> Option> { let block = parse( working_set, - Some(fp_str), + fp.to_str(), file.get_content(None).as_bytes(), false, ); - let file_span = working_set.get_span_for_filename(fp_str)?; - let offset = file_span.start; - let mut references: Vec = find_reference_by_id(&block, working_set, id); - - // NOTE: for arguments whose declaration is in a signature - // which is not covered in the AST - if let Id::Variable(vid) = id { - let decl_span = working_set.get_variable(*vid).declaration_span; - if file_span.contains_span(decl_span) - && decl_span.end > decl_span.start - && !references.contains(&decl_span) - { - references.push(decl_span); - } - } - let occurs: Vec = references - .iter() - .map(|span| span_to_range(span, file, offset)) - .collect(); + let references: Vec = find_reference_by_id(&block, working_set, id); // add_block to avoid repeated parsing working_set.add_block(block); - (!occurs.is_empty()).then_some(occurs) + (!references.is_empty()).then_some(references) } impl LanguageServer { @@ -284,6 +265,7 @@ impl LanguageServer { .filter_map(|p| p.ok()) .collect(); let len = scripts.len(); + let definition_span = Self::find_definition_span_by_id(&working_set, &id); for (i, fp) in scripts.iter().enumerate() { #[cfg(test)] @@ -324,7 +306,34 @@ impl LanguageServer { } &FullTextDocument::new("nu".to_string(), 0, content_string.into()) }; - let _ = find_reference_in_file(&mut working_set, file, fp, &id).map(|ranges| { + let _ = find_reference_in_file(&mut working_set, file, fp, &id).map(|mut refs| { + let file_span = working_set + .get_span_for_filename(fp.to_string_lossy().as_ref()) + .unwrap_or(Span::unknown()); + // NOTE: for arguments whose declaration is in a signature + // which is not covered in the AST + if let (Id::Variable(_), Some(decl_span)) = (&id, definition_span) { + if file_span.contains_span(decl_span) + && decl_span.end > decl_span.start + && !refs.contains(&decl_span) + { + let leading_dashes = working_set + .get_span_contents(decl_span) + .iter() + // remove leading dashes for flags + .take_while(|c| *c == &b'-') + .count(); + let start = decl_span.start + leading_dashes; + refs.push(Span { + start, + end: start + span.end - span.start, + }); + } + } + let ranges = refs + .iter() + .map(|span| span_to_range(span, file, file_span.start)) + .collect(); data_sender .send(InternalMessage::RangeMessage(RangePerDoc { uri, ranges })) .ok(); @@ -693,7 +702,7 @@ mod tests { "newText": "new" }, { - "range": { "start": { "line": 1, "character": 2 }, "end": { "line": 1, "character": 7 } }, + "range": { "start": { "line": 1, "character": 4 }, "end": { "line": 1, "character": 9 } }, "newText": "new" } ] diff --git a/tests/fixtures/lsp/workspace/foo.nu b/tests/fixtures/lsp/workspace/foo.nu index 4b9adcf642..30c4326f68 100644 --- a/tests/fixtures/lsp/workspace/foo.nu +++ b/tests/fixtures/lsp/workspace/foo.nu @@ -1,5 +1,5 @@ export def foooo [ - param: int + --param(-p): int ] { $param }