Skip to content

Commit bc04d6b

Browse files
committed
Implement goto implementations for entity to component declaration
1 parent d26d4fc commit bc04d6b

File tree

5 files changed

+83
-17
lines changed

5 files changed

+83
-17
lines changed

vhdl_lang/src/analysis.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ mod visibility;
3232
mod tests;
3333

3434
pub use self::root::DesignRoot;
35-
pub use named_entity::{AnyEnt, AnyEntKind, EntRef, EntityId, HasEntityId, Related};
35+
pub use named_entity::{AnyEnt, AnyEntKind, Design, EntRef, EntityId, HasEntityId, Related};

vhdl_lang/src/analysis/root.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,20 @@ impl DesignRoot {
467467
NotFound
468468
}
469469

470+
pub fn search_library(
471+
&self,
472+
library_name: &Symbol,
473+
searcher: &mut impl Searcher,
474+
) -> SearchResult {
475+
if let Some(library) = self.libraries.get(library_name) {
476+
for unit_id in library.sorted_unit_ids() {
477+
let unit = library.units.get(unit_id.key()).unwrap();
478+
return_if_found!(unit.unit.write().search(searcher));
479+
}
480+
}
481+
NotFound
482+
}
483+
470484
pub fn symbol_utf8(&self, name: &str) -> Symbol {
471485
self.symbols.symtab().insert_utf8(name)
472486
}

vhdl_lang/src/ast/search.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,35 @@ impl<'a, T: Fn(EntRef<'a>) -> bool> Searcher for FindEnt<'a, T> {
13431343
}
13441344
}
13451345

1346+
pub struct FindAllEnt<'a, T: Fn(EntRef<'a>) -> bool> {
1347+
root: &'a DesignRoot,
1348+
cond: T,
1349+
pub result: Vec<EntRef<'a>>,
1350+
}
1351+
1352+
impl<'a, T: Fn(EntRef<'a>) -> bool> FindAllEnt<'a, T> {
1353+
pub fn new(root: &'a DesignRoot, cond: T) -> FindAllEnt<'a, T> {
1354+
FindAllEnt {
1355+
root,
1356+
cond,
1357+
result: Vec::default(),
1358+
}
1359+
}
1360+
}
1361+
1362+
impl<'a, T: Fn(EntRef<'a>) -> bool> Searcher for FindAllEnt<'a, T> {
1363+
fn search_decl(&mut self, decl: FoundDeclaration) -> SearchState {
1364+
if let Some(id) = decl.ent_id() {
1365+
let ent = self.root.get_ent(id);
1366+
if (self.cond)(ent) {
1367+
self.result.push(ent);
1368+
}
1369+
}
1370+
1371+
SearchState::NotFinished
1372+
}
1373+
}
1374+
13461375
// Search for a declaration/definition and format it
13471376
pub struct FormatDeclaration<'a> {
13481377
ent: EntRef<'a>,

vhdl_lang/src/project.rs

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

7-
use crate::analysis::{AnyEnt, AnyEntKind, DesignRoot, EntRef, Related};
7+
use crate::analysis::{AnyEnt, AnyEntKind, Design, DesignRoot, EntRef, Related};
8+
use crate::ast::search::FindAllEnt;
89
use crate::ast::{DesignFile, Designator};
910
use crate::config::Config;
1011
use crate::data::*;
@@ -237,32 +238,50 @@ impl Project {
237238
}
238239
}
239240

240-
/// Find entity with same name as component in the library
241+
fn get_library(&self, source: &Source) -> Option<Symbol> {
242+
let file = self.files.get(source.file_name())?;
243+
file.library_names.iter().next().cloned()
244+
}
245+
241246
pub fn find_implementation<'a>(
242247
&'a self,
243248
source: &Source,
244249
cursor: Position,
245-
) -> Option<EntRef<'a>> {
250+
) -> Option<Vec<EntRef<'a>>> {
246251
let ent = self.find_declaration(source, cursor)?;
247-
if !matches!(ent.kind(), AnyEntKind::Component(_)) {
248-
return None;
249-
}
250252

251253
let ident = if let Designator::Identifier(ident) = ent.designator() {
252254
ident
253255
} else {
254256
return None;
255257
};
256258

257-
let decl_pos = ent.decl_pos()?;
258-
259-
let file = self.files.get(decl_pos.source().file_name())?;
260-
for library_name in file.library_names.iter() {
261-
if let Some(design) = self.root.get_design_entity(library_name, ident) {
262-
return Some(design.into());
259+
match ent.kind() {
260+
// Find entity with same name as component in the library
261+
AnyEntKind::Component(_) => {
262+
let decl_pos = ent.decl_pos()?;
263+
let library_name = self.get_library(decl_pos.source())?;
264+
let design = self.root.get_design_entity(&library_name, ident)?;
265+
Some(vec![design.into()])
266+
}
267+
// Find all components with same name as entity in the library
268+
AnyEntKind::Design(Design::Entity(..)) => {
269+
let decl_pos = ent.decl_pos()?;
270+
let library_name = self.get_library(decl_pos.source())?;
271+
272+
let mut searcher = FindAllEnt::new(&self.root, |ent| {
273+
matches!(ent.kind(), AnyEntKind::Component(_))
274+
&& matches!(
275+
ent.designator(),
276+
Designator::Identifier(comp_ident) if comp_ident == ident
277+
)
278+
});
279+
280+
let _ = self.root.search_library(&library_name, &mut searcher);
281+
Some(searcher.result)
263282
}
283+
_ => None,
264284
}
265-
None
266285
}
267286

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

vhdl_ls/src/vhdl_server.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,16 +349,20 @@ impl VHDLServer {
349349
pub fn text_document_implementation(
350350
&mut self,
351351
params: &TextDocumentPositionParams,
352-
) -> Option<Location> {
352+
) -> Option<GotoDefinitionResponse> {
353353
let source = self
354354
.project
355355
.get_source(&uri_to_file_name(&params.text_document.uri))?;
356356

357-
let ent = self
357+
let ents = self
358358
.project
359359
.find_implementation(&source, from_lsp_pos(params.position))?;
360360

361-
Some(srcpos_to_location(ent.decl_pos()?))
361+
Some(GotoDefinitionResponse::Array(
362+
ents.into_iter()
363+
.filter_map(|ent| ent.decl_pos().map(srcpos_to_location))
364+
.collect(),
365+
))
362366
}
363367

364368
pub fn text_document_hover(&mut self, params: &TextDocumentPositionParams) -> Option<Hover> {

0 commit comments

Comments
 (0)