Skip to content

Commit 1ba8c3a

Browse files
committed
Implement LSP goto declaration and definition differently
1 parent 0adce9f commit 1ba8c3a

File tree

9 files changed

+102
-24
lines changed

9 files changed

+102
-24
lines changed

vhdl_lang/src/analysis/declarative.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,6 @@ impl<'a> AnalyzeContext<'a> {
640640
if let AnyEntKind::Type(Type::Protected(ptype_region, is_body)) =
641641
ent.kind()
642642
{
643-
body.type_reference.set_unique_reference(ent);
644643
let region = Scope::extend(ptype_region, Some(scope));
645644
self.analyze_declarative_part(
646645
&region,

vhdl_lang/src/analysis/root.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,21 @@ impl DesignRoot {
351351
Some(self.get_ent(id))
352352
}
353353

354+
pub fn find_definition_of<'a>(&'a self, decl: EntRef<'a>) -> Option<EntRef<'a>> {
355+
if decl.is_protected_type()
356+
|| decl.is_subprogram_decl()
357+
|| decl.kind().is_deferred_constant()
358+
{
359+
let mut searcher = FindEnt::new(self, |ent| ent.is_declared_by(decl));
360+
let _ = self.search(&mut searcher);
361+
362+
Some(searcher.result.unwrap_or(decl))
363+
} else {
364+
// The definition is the same as the declaration
365+
Some(decl)
366+
}
367+
}
368+
354369
#[cfg(test)]
355370
pub fn search_reference_pos(&self, source: &Source, cursor: Position) -> Option<SrcPos> {
356371
self.search_reference(source, cursor)

vhdl_lang/src/analysis/tests/protected_type.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ end package;",
265265

266266
assert_eq!(
267267
root.search_reference_pos(code.source(), code.s("prot_t", 2).start()),
268-
Some(code.s1("prot_t").pos())
268+
Some(code.s("prot_t", 2).pos())
269269
);
270270

271271
assert_eq!(
@@ -284,4 +284,9 @@ end package;",
284284
code.s("prot_t", 3).pos()
285285
]
286286
);
287+
288+
assert_eq!(
289+
root.find_definition_of(ptype).unwrap().decl_pos(),
290+
Some(&code.s("prot_t", 2).pos())
291+
);
287292
}

vhdl_lang/src/analysis/tests/resolves_names.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,16 @@ end;
17871787
code.s("myfun", 3).pos()
17881788
]
17891789
);
1790+
1791+
assert_eq!(
1792+
root.find_definition_of(
1793+
root.search_reference(code.source(), code.s1("myfun").start())
1794+
.unwrap()
1795+
)
1796+
.unwrap()
1797+
.decl_pos(),
1798+
Some(&code.s("myfun", 2).pos())
1799+
);
17901800
}
17911801

17921802
#[test]
@@ -1820,4 +1830,14 @@ end package body;
18201830
&root.find_all_references_pos(&code.s("c0", 2).pos()),
18211831
&references,
18221832
);
1833+
1834+
assert_eq!(
1835+
root.find_definition_of(
1836+
root.search_reference(code.source(), code.s1("c0").start())
1837+
.unwrap()
1838+
)
1839+
.unwrap()
1840+
.decl_pos(),
1841+
Some(&code.s("c0", 2).pos())
1842+
);
18231843
}

vhdl_lang/src/ast.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,6 @@ pub struct ProtectedTypeDeclaration {
537537
/// LRM 5.6.3 Protected type bodies
538538
#[derive(PartialEq, Debug, Clone)]
539539
pub struct ProtectedTypeBody {
540-
pub type_reference: Reference,
541540
pub decl: Vec<Declaration>,
542541
}
543542

vhdl_lang/src/ast/search.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -674,18 +674,12 @@ impl Search for DiscreteRange {
674674

675675
impl Search for TypeDeclaration {
676676
fn search(&mut self, searcher: &mut impl Searcher) -> SearchResult {
677-
if !matches!(self.def, TypeDefinition::ProtectedBody(_)) {
678-
return_if_found!(searcher
679-
.search_decl(FoundDeclaration::Type(self))
680-
.or_not_found());
681-
}
677+
return_if_found!(searcher
678+
.search_decl(FoundDeclaration::Type(self))
679+
.or_not_found());
682680

683681
match self.def {
684682
TypeDefinition::ProtectedBody(ref mut body) => {
685-
// Protected type body is not considered a declaration
686-
return_if_found!(searcher
687-
.search_pos_with_ref(self.ident.pos(), &mut body.type_reference)
688-
.or_not_found());
689683
return_if_found!(body.decl.search(searcher));
690684
}
691685
TypeDefinition::Protected(ref mut prot_decl) => {
@@ -1318,6 +1312,37 @@ impl Searcher for ItemAtCursor {
13181312
}
13191313
}
13201314

1315+
// Search for reference to declaration/definition at cursor
1316+
pub struct FindEnt<'a, T: Fn(EntRef<'a>) -> bool> {
1317+
root: &'a DesignRoot,
1318+
cond: T,
1319+
pub result: Option<EntRef<'a>>,
1320+
}
1321+
1322+
impl<'a, T: Fn(EntRef<'a>) -> bool> FindEnt<'a, T> {
1323+
pub fn new(root: &'a DesignRoot, cond: T) -> FindEnt<'a, T> {
1324+
FindEnt {
1325+
root,
1326+
cond,
1327+
result: None,
1328+
}
1329+
}
1330+
}
1331+
1332+
impl<'a, T: Fn(EntRef<'a>) -> bool> Searcher for FindEnt<'a, T> {
1333+
fn search_decl(&mut self, decl: FoundDeclaration) -> SearchState {
1334+
if let Some(id) = decl.ent_id() {
1335+
let ent = self.root.get_ent(id);
1336+
if (self.cond)(ent) {
1337+
self.result = Some(ent);
1338+
return SearchState::Finished(SearchResult::Found);
1339+
}
1340+
}
1341+
1342+
SearchState::NotFinished
1343+
}
1344+
}
1345+
13211346
// Search for a declaration/definition and format it
13221347
pub struct FormatDeclaration<'a> {
13231348
ent: EntRef<'a>,

vhdl_lang/src/project.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Copyright (c) 2018, Olof Kraigher [email protected]
66

7-
use crate::analysis::{AnyEnt, DesignRoot, EntRef};
7+
use crate::analysis::{AnyEnt, DesignRoot, EntRef, Related};
88
use crate::ast::DesignFile;
99
use crate::config::Config;
1010
use crate::data::*;
@@ -222,8 +222,19 @@ impl Project {
222222
///
223223
/// If the character value is greater than the line length it defaults back to the
224224
/// line length.
225-
pub fn search_reference<'a>(&'a self, source: &Source, cursor: Position) -> Option<EntRef<'a>> {
226-
self.root.search_reference(source, cursor)
225+
pub fn find_definition<'a>(&'a self, source: &Source, cursor: Position) -> Option<EntRef<'a>> {
226+
let ent = self.root.search_reference(source, cursor)?;
227+
self.root.find_definition_of(ent)
228+
}
229+
230+
pub fn find_declaration<'a>(&'a self, source: &Source, cursor: Position) -> Option<EntRef<'a>> {
231+
let ent = self.root.search_reference(source, cursor)?;
232+
233+
if let Related::DeclaredBy(other) = ent.related {
234+
Some(other)
235+
} else {
236+
Some(ent)
237+
}
227238
}
228239

229240
/// Search for the declaration at decl_pos and format it

vhdl_lang/src/syntax/type_declaration.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ pub fn parse_type_declaration(
257257
// @TODO check name
258258
stream.pop_if_kind(Identifier)?;
259259
stream.expect_kind(SemiColon)?;
260-
TypeDefinition::ProtectedBody(ProtectedTypeBody {type_reference: Reference::default(), decl})
260+
TypeDefinition::ProtectedBody(ProtectedTypeBody {decl})
261261
} else {
262262
let (protected_type_decl, end_ident) = parse_protected_type_declaration(stream, diagnostics)?;
263263
diagnostics.push_some(error_on_end_identifier_mismatch(&ident, &end_ident));
@@ -699,10 +699,7 @@ end protected body;
699699
code.with_stream_no_diagnostics(parse_type_declaration),
700700
TypeDeclaration {
701701
ident,
702-
def: TypeDefinition::ProtectedBody(ProtectedTypeBody {
703-
type_reference: Reference::default(),
704-
decl
705-
}),
702+
def: TypeDefinition::ProtectedBody(ProtectedTypeBody { decl }),
706703
}
707704
)
708705
}

vhdl_ls/src/vhdl_server.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl VHDLServer {
327327

328328
let ent = self
329329
.project
330-
.search_reference(&source, from_lsp_pos(params.position))?;
330+
.find_declaration(&source, from_lsp_pos(params.position))?;
331331
Some(srcpos_to_location(ent.decl_pos()?))
332332
}
333333

@@ -336,7 +336,14 @@ impl VHDLServer {
336336
&mut self,
337337
params: &TextDocumentPositionParams,
338338
) -> Option<Location> {
339-
self.text_document_declaration(params)
339+
let source = self
340+
.project
341+
.get_source(&uri_to_file_name(&params.text_document.uri))?;
342+
343+
let ent = self
344+
.project
345+
.find_definition(&source, from_lsp_pos(params.position))?;
346+
Some(srcpos_to_location(ent.decl_pos()?))
340347
}
341348

342349
pub fn text_document_hover(&mut self, params: &TextDocumentPositionParams) -> Option<Hover> {
@@ -345,7 +352,7 @@ impl VHDLServer {
345352
.get_source(&uri_to_file_name(&params.text_document.uri))?;
346353
let ent = self
347354
.project
348-
.search_reference(&source, from_lsp_pos(params.position))?;
355+
.find_declaration(&source, from_lsp_pos(params.position))?;
349356

350357
let value = self.project.format_declaration(ent)?;
351358

@@ -365,7 +372,7 @@ impl VHDLServer {
365372
&params.text_document_position.text_document.uri,
366373
))
367374
.and_then(|source| {
368-
self.project.search_reference(
375+
self.project.find_declaration(
369376
&source,
370377
from_lsp_pos(params.text_document_position.position),
371378
)

0 commit comments

Comments
 (0)