Skip to content

Commit d26d4fc

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

File tree

7 files changed

+83
-10
lines changed

7 files changed

+83
-10
lines changed

vhdl_lang/src/analysis/analyze.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,9 @@ impl<'a> AnalyzeContext<'a> {
355355
if let Some(unit) = self.get_primary_unit(library_name, primary_name) {
356356
let data = self.get_analysis(Some(pos), unit)?;
357357
if let AnyDesignUnit::Primary(primary) = data.deref() {
358-
if let Some(ent) = primary.ent_id() {
359-
let design = DesignEnt::from_any(self.arena.get(ent)).map_err(|ent| {
358+
if let Some(id) = primary.ent_id() {
359+
let ent = self.arena.get(id);
360+
let design = DesignEnt::from_any(ent).ok_or_else(|| {
360361
// Almost impossible but better not fail silently
361362
Diagnostic::error(
362363
pos,

vhdl_lang/src/analysis/named_entity/design.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ impl<'a> Design<'a> {
4747
pub struct DesignEnt<'a>(pub EntRef<'a>);
4848

4949
impl<'a> DesignEnt<'a> {
50-
pub fn from_any(ent: &'a AnyEnt) -> Result<DesignEnt<'a>, EntRef<'a>> {
50+
pub fn from_any(ent: &'a AnyEnt) -> Option<DesignEnt<'a>> {
5151
if matches!(ent.kind(), AnyEntKind::Design(..)) {
52-
Ok(DesignEnt(ent))
52+
Some(DesignEnt(ent))
5353
} else {
54-
Err(ent)
54+
None
5555
}
5656
}
5757

vhdl_lang/src/analysis/names.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,12 +1472,12 @@ impl<'a> AnalyzeContext<'a> {
14721472
Ok(subtype.type_mark().selected(prefix_pos, suffix)?.into_any())
14731473
}
14741474
AnyEntKind::Design(_) => {
1475-
let design = DesignEnt::from_any(prefix).map_err(|ent| {
1475+
let design = DesignEnt::from_any(prefix).ok_or_else(|| {
14761476
Diagnostic::error(
14771477
&suffix.pos,
14781478
format!(
14791479
"Internal error when expecting design unit, got {}",
1480-
ent.describe()
1480+
prefix.describe()
14811481
),
14821482
)
14831483
})?;

vhdl_lang/src/analysis/root.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,26 @@ impl DesignRoot {
317317
.map(|library| &library.units)
318318
}
319319

320+
pub(crate) fn get_design_entity<'a>(
321+
&'a self,
322+
library_name: &Symbol,
323+
ident: &Symbol,
324+
) -> Option<DesignEnt<'a>> {
325+
let units = self.get_library_units(library_name)?;
326+
let unit = units.get(&UnitKey::Primary(ident.clone()))?;
327+
let data = self.get_analysis(unit);
328+
329+
if let AnyDesignUnit::Primary(primary) = data.deref() {
330+
if let Some(id) = primary.ent_id() {
331+
let design = DesignEnt::from_any(self.arenas.get(id))?;
332+
if matches!(design.kind(), Design::Entity(..)) {
333+
return Some(design);
334+
}
335+
}
336+
}
337+
None
338+
}
339+
320340
/// Get a named entity corresponding to the library
321341
pub(super) fn get_library_arena(
322342
&self,

vhdl_lang/src/project.rs

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

7-
use crate::analysis::{AnyEnt, DesignRoot, EntRef, Related};
8-
use crate::ast::DesignFile;
7+
use crate::analysis::{AnyEnt, AnyEntKind, DesignRoot, EntRef, Related};
8+
use crate::ast::{DesignFile, Designator};
99
use crate::config::Config;
1010
use crate::data::*;
1111
use crate::syntax::VHDLParser;
@@ -237,6 +237,34 @@ impl Project {
237237
}
238238
}
239239

240+
/// Find entity with same name as component in the library
241+
pub fn find_implementation<'a>(
242+
&'a self,
243+
source: &Source,
244+
cursor: Position,
245+
) -> Option<EntRef<'a>> {
246+
let ent = self.find_declaration(source, cursor)?;
247+
if !matches!(ent.kind(), AnyEntKind::Component(_)) {
248+
return None;
249+
}
250+
251+
let ident = if let Designator::Identifier(ident) = ent.designator() {
252+
ident
253+
} else {
254+
return None;
255+
};
256+
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());
263+
}
264+
}
265+
None
266+
}
267+
240268
/// Search for the declaration at decl_pos and format it
241269
pub fn format_declaration(&self, ent: &AnyEnt) -> Option<String> {
242270
self.root.format_declaration(ent)

vhdl_ls/src/stdio_server.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ impl ConnectionRpcChannel {
138138
}
139139
Err(request) => request,
140140
};
141+
let request = match extract::<request::GotoImplementation>(request) {
142+
Ok((id, params)) => {
143+
let result =
144+
server.text_document_implementation(&params.text_document_position_params);
145+
self.send_response(lsp_server::Response::new_ok(id, result));
146+
return;
147+
}
148+
Err(request) => request,
149+
};
141150
let request = match extract::<request::HoverRequest>(request) {
142151
Ok((id, params)) => {
143152
let result = server.text_document_hover(&params.text_document_position_params);

vhdl_ls/src/vhdl_server.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ impl VHDLServer {
116116
definition_provider: Some(OneOf::Left(true)),
117117
hover_provider: Some(HoverProviderCapability::Simple(true)),
118118
references_provider: Some(OneOf::Left(true)),
119+
implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
119120
..Default::default()
120121
};
121122

@@ -331,7 +332,6 @@ impl VHDLServer {
331332
Some(srcpos_to_location(ent.decl_pos()?))
332333
}
333334

334-
// Copy goto-declaration for now
335335
pub fn text_document_definition(
336336
&mut self,
337337
params: &TextDocumentPositionParams,
@@ -346,6 +346,21 @@ impl VHDLServer {
346346
Some(srcpos_to_location(ent.decl_pos()?))
347347
}
348348

349+
pub fn text_document_implementation(
350+
&mut self,
351+
params: &TextDocumentPositionParams,
352+
) -> Option<Location> {
353+
let source = self
354+
.project
355+
.get_source(&uri_to_file_name(&params.text_document.uri))?;
356+
357+
let ent = self
358+
.project
359+
.find_implementation(&source, from_lsp_pos(params.position))?;
360+
361+
Some(srcpos_to_location(ent.decl_pos()?))
362+
}
363+
349364
pub fn text_document_hover(&mut self, params: &TextDocumentPositionParams) -> Option<Hover> {
350365
let source = self
351366
.project

0 commit comments

Comments
 (0)