Skip to content

Commit 29a7788

Browse files
author
Johannes Zeppenfeld
committed
Implement language server textDocument/hover by returning the formatted declaration
1 parent 34d8276 commit 29a7788

File tree

5 files changed

+226
-24
lines changed

5 files changed

+226
-24
lines changed

vhdl_lang/src/analysis/root.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ impl DesignRoot {
317317
ItemAtCursor::search(self, source, cursor)
318318
}
319319

320+
/// Search for the declaration at decl_pos and format it
321+
pub fn format_declaration(&self, decl_pos: &SrcPos) -> Option<String> {
322+
FormatDeclaration::search(self, decl_pos)
323+
}
324+
325+
/// Search for all references to the declaration at decl_pos
320326
pub fn find_all_references(&self, decl_pos: &SrcPos) -> Vec<SrcPos> {
321327
FindAllReferences::search(self, decl_pos)
322328
}

vhdl_lang/src/ast/search.rs

Lines changed: 183 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,31 @@ impl SearchState {
3838
}
3939
}
4040

41+
#[derive(PartialEq, Debug, Clone)]
42+
pub enum FoundDeclaration<'a> {
43+
Object(&'a ObjectDeclaration),
44+
InterfaceObject(&'a InterfaceObjectDeclaration),
45+
File(&'a FileDeclaration),
46+
Type(&'a TypeDeclaration),
47+
Component(&'a ComponentDeclaration),
48+
//Attribute(&'a AttributeDeclaration),
49+
Alias(&'a AliasDeclaration),
50+
Function(&'a FunctionSpecification),
51+
Procedure(&'a ProcedureSpecification),
52+
Library(&'a Ident),
53+
Package(&'a PackageDeclaration),
54+
PackageInstance(&'a PackageInstantiation),
55+
Configuration(&'a ConfigurationDeclaration),
56+
Entity(&'a EntityDeclaration),
57+
Context(&'a ContextDeclaration),
58+
ForIndex(&'a Ident, &'a DiscreteRange),
59+
ForGenerateIndex(&'a Option<Ident>, &'a ForGenerateStatement),
60+
// Not used
61+
//ConcurrentStatement(&'a LabeledConcurrentStatement),
62+
//GenerateBody(&'a GenerateBody),
63+
//SequentialStatement(&'a LabeledSequentialStatement),
64+
}
65+
4166
pub trait Searcher {
4267
/// Search an position that has a reference to a declaration
4368
fn search_pos_with_ref(&mut self, _pos: &SrcPos, _ref: &Reference) -> SearchState {
@@ -63,6 +88,11 @@ pub trait Searcher {
6388
NotFinished
6489
}
6590

91+
/// Search a declaration of a named entity
92+
fn search_decl(&mut self, pos: &SrcPos, _decl: FoundDeclaration) -> SearchState {
93+
self.search_decl_pos(pos)
94+
}
95+
6696
fn search_with_pos(&mut self, _pos: &SrcPos) -> SearchState {
6797
NotFinished
6898
}
@@ -285,7 +315,9 @@ impl Search for LabeledSequentialStatement {
285315
} = loop_stmt;
286316
match iteration_scheme {
287317
Some(IterationScheme::For(ref index, ref drange)) => {
288-
return_if_found!(searcher.search_decl_pos(index.pos()).or_not_found());
318+
return_if_found!(searcher
319+
.search_decl(index.pos(), FoundDeclaration::ForIndex(&index, &drange))
320+
.or_not_found());
289321
return_if_found!(drange.search(searcher));
290322
return_if_found!(statements.search(searcher));
291323
}
@@ -400,7 +432,12 @@ impl Search for LabeledConcurrentStatement {
400432
discrete_range,
401433
body,
402434
} = gen;
403-
return_if_found!(searcher.search_decl_pos(index_name.pos()).or_not_found());
435+
return_if_found!(searcher
436+
.search_decl(
437+
index_name.pos(),
438+
FoundDeclaration::ForGenerateIndex(&self.label, &gen)
439+
)
440+
.or_not_found());
404441
return_if_found!(discrete_range.search(searcher));
405442
body.search(searcher)
406443
}
@@ -623,7 +660,9 @@ impl Search for TypeDeclaration {
623660
return_if_found!(body.decl.search(searcher));
624661
}
625662
TypeDefinition::Protected(ref prot_decl) => {
626-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
663+
return_if_found!(searcher
664+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
665+
.or_not_found());
627666
for item in prot_decl.items.iter() {
628667
match item {
629668
ProtectedTypeDeclarativeItem::Subprogram(ref subprogram) => {
@@ -633,17 +672,23 @@ impl Search for TypeDeclaration {
633672
}
634673
}
635674
TypeDefinition::Record(ref element_decls) => {
636-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
675+
return_if_found!(searcher
676+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
677+
.or_not_found());
637678
for elem in element_decls {
638679
return_if_found!(elem.subtype.search(searcher));
639680
}
640681
}
641682
TypeDefinition::Access(ref subtype_indication) => {
642-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
683+
return_if_found!(searcher
684+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
685+
.or_not_found());
643686
return_if_found!(subtype_indication.search(searcher));
644687
}
645688
TypeDefinition::Array(ref indexes, ref subtype_indication) => {
646-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
689+
return_if_found!(searcher
690+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
691+
.or_not_found());
647692
for index in indexes.iter() {
648693
match index {
649694
ArrayIndex::IndexSubtypeDefintion(ref type_mark) => {
@@ -657,15 +702,21 @@ impl Search for TypeDeclaration {
657702
return_if_found!(subtype_indication.search(searcher));
658703
}
659704
TypeDefinition::Subtype(ref subtype_indication) => {
660-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
705+
return_if_found!(searcher
706+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
707+
.or_not_found());
661708
return_if_found!(subtype_indication.search(searcher));
662709
}
663710
TypeDefinition::Integer(ref range) => {
664-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
711+
return_if_found!(searcher
712+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
713+
.or_not_found());
665714
return_if_found!(range.search(searcher));
666715
}
667716
TypeDefinition::File(ref type_mark) => {
668-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
717+
return_if_found!(searcher
718+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
719+
.or_not_found());
669720
return_if_found!(type_mark.search(searcher));
670721
}
671722
TypeDefinition::Incomplete(ref reference) => {
@@ -676,7 +727,9 @@ impl Search for TypeDeclaration {
676727
}
677728
// @TODO others
678729
_ => {
679-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
730+
return_if_found!(searcher
731+
.search_decl(self.ident.pos(), FoundDeclaration::Type(&self))
732+
.or_not_found());
680733
}
681734
}
682735
NotFound
@@ -776,7 +829,9 @@ impl Search for WithPos<Expression> {
776829

777830
impl Search for ObjectDeclaration {
778831
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
779-
return_if_found!(searcher.search_decl_pos(self.ident.pos()).or_not_found());
832+
return_if_found!(searcher
833+
.search_decl(self.ident.pos(), FoundDeclaration::Object(&self))
834+
.or_not_found());
780835
return_if_found!(self.subtype_indication.search(searcher));
781836
if let Some(ref expr) = self.expression {
782837
expr.search(searcher)
@@ -825,7 +880,9 @@ impl Search for Declaration {
825880
name,
826881
signature,
827882
} = alias;
828-
return_if_found!(searcher.search_decl_pos(&designator.pos).or_not_found());
883+
return_if_found!(searcher
884+
.search_decl(&designator.pos, FoundDeclaration::Alias(&alias))
885+
.or_not_found());
829886
return_if_found!(subtype_indication.search(searcher));
830887
return_if_found!(name.search(searcher));
831888
if let Some(signature) = signature {
@@ -841,7 +898,9 @@ impl Search for Declaration {
841898
generic_list,
842899
port_list,
843900
} = component;
844-
return_if_found!(searcher.search_decl_pos(ident.pos()).or_not_found());
901+
return_if_found!(searcher
902+
.search_decl(ident.pos(), FoundDeclaration::Component(&component))
903+
.or_not_found());
845904
return_if_found!(generic_list.search(searcher));
846905
return_if_found!(port_list.search(searcher));
847906
}
@@ -853,7 +912,9 @@ impl Search for Declaration {
853912
open_info,
854913
file_name,
855914
} = file;
856-
return_if_found!(searcher.search_decl_pos(ident.pos()).or_not_found());
915+
return_if_found!(searcher
916+
.search_decl(ident.pos(), FoundDeclaration::File(&file))
917+
.or_not_found());
857918
return_if_found!(subtype_indication.search(searcher));
858919
return_if_found!(open_info.search(searcher));
859920
return_if_found!(file_name.search(searcher));
@@ -870,7 +931,9 @@ impl Search for InterfaceDeclaration {
870931
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
871932
match self {
872933
InterfaceDeclaration::Object(ref decl) => {
873-
return_if_found!(searcher.search_decl_pos(decl.ident.pos()).or_not_found());
934+
return_if_found!(searcher
935+
.search_decl(decl.ident.pos(), FoundDeclaration::InterfaceObject(&decl))
936+
.or_not_found());
874937
return_if_found!(decl.subtype_indication.search(searcher));
875938
return_if_found!(decl.expression.search(searcher));
876939
}
@@ -896,7 +959,7 @@ impl Search for SubprogramDeclaration {
896959
impl Search for ProcedureSpecification {
897960
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
898961
return_if_found!(searcher
899-
.search_decl_pos(&self.designator.pos)
962+
.search_decl(&self.designator.pos, FoundDeclaration::Procedure(&self))
900963
.or_not_found());
901964
self.parameter_list.search(searcher)
902965
}
@@ -905,7 +968,7 @@ impl Search for ProcedureSpecification {
905968
impl Search for FunctionSpecification {
906969
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
907970
return_if_found!(searcher
908-
.search_decl_pos(&self.designator.pos)
971+
.search_decl(&self.designator.pos, FoundDeclaration::Function(&self))
909972
.or_not_found());
910973
return_if_found!(self.parameter_list.search(searcher));
911974
self.return_type.search(searcher)
@@ -915,7 +978,9 @@ impl Search for FunctionSpecification {
915978
impl Search for LibraryClause {
916979
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
917980
for name in self.name_list.iter() {
918-
return_if_found!(searcher.search_decl_pos(name.pos()).or_not_found());
981+
return_if_found!(searcher
982+
.search_decl(name.pos(), FoundDeclaration::Library(&name))
983+
.or_not_found());
919984
}
920985
NotFound
921986
}
@@ -962,7 +1027,9 @@ impl Search for EntityDeclaration {
9621027
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
9631028
return_if_finished!(searcher.search_source(self.source()));
9641029
return_if_found!(self.context_clause.search(searcher));
965-
return_if_found!(searcher.search_decl_pos(self.ident().pos()).or_not_found());
1030+
return_if_found!(searcher
1031+
.search_decl(self.ident().pos(), FoundDeclaration::Entity(&self))
1032+
.or_not_found());
9661033
return_if_found!(self.generic_clause.search(searcher));
9671034
return_if_found!(self.port_clause.search(searcher));
9681035
return_if_found!(self.decl.search(searcher));
@@ -984,7 +1051,9 @@ impl Search for PackageDeclaration {
9841051
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
9851052
return_if_finished!(searcher.search_source(self.source()));
9861053
return_if_found!(self.context_clause.search(searcher));
987-
return_if_found!(searcher.search_decl_pos(self.ident().pos()).or_not_found());
1054+
return_if_found!(searcher
1055+
.search_decl(self.ident().pos(), FoundDeclaration::Package(&self))
1056+
.or_not_found());
9881057
return_if_found!(self.generic_clause.search(searcher));
9891058
self.decl.search(searcher)
9901059
}
@@ -1003,7 +1072,9 @@ impl Search for PackageInstantiation {
10031072
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
10041073
return_if_finished!(searcher.search_source(self.source()));
10051074
return_if_found!(self.context_clause.search(searcher));
1006-
return_if_found!(searcher.search_decl_pos(self.ident().pos()).or_not_found());
1075+
return_if_found!(searcher
1076+
.search_decl(self.ident().pos(), FoundDeclaration::PackageInstance(&self))
1077+
.or_not_found());
10071078
self.package_name.search(searcher)
10081079
}
10091080
}
@@ -1012,15 +1083,19 @@ impl Search for ConfigurationDeclaration {
10121083
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
10131084
return_if_finished!(searcher.search_source(self.source()));
10141085
return_if_found!(self.context_clause.search(searcher));
1015-
return_if_found!(searcher.search_decl_pos(self.ident().pos()).or_not_found());
1086+
return_if_found!(searcher
1087+
.search_decl(self.ident().pos(), FoundDeclaration::Configuration(&self))
1088+
.or_not_found());
10161089
self.entity_name.search(searcher)
10171090
}
10181091
}
10191092

10201093
impl Search for ContextDeclaration {
10211094
fn search(&self, searcher: &mut impl Searcher) -> SearchResult {
10221095
return_if_finished!(searcher.search_source(self.source()));
1023-
return_if_found!(searcher.search_decl_pos(self.ident().pos()).or_not_found());
1096+
return_if_found!(searcher
1097+
.search_decl(self.ident().pos(), FoundDeclaration::Context(&self))
1098+
.or_not_found());
10241099
self.items.search(searcher)
10251100
}
10261101
}
@@ -1108,7 +1183,91 @@ impl Searcher for ItemAtCursor {
11081183
}
11091184
}
11101185

1111-
// Search for all reference to declaration/defintion
1186+
// Search for a declaration/definition and format it
1187+
pub struct FormatDeclaration {
1188+
decl_pos: SrcPos,
1189+
result: Option<String>,
1190+
}
1191+
1192+
impl FormatDeclaration {
1193+
pub fn new(decl_pos: &SrcPos) -> FormatDeclaration {
1194+
FormatDeclaration {
1195+
decl_pos: decl_pos.clone(),
1196+
result: None,
1197+
}
1198+
}
1199+
1200+
pub fn search(searchable: &impl Search, decl_pos: &SrcPos) -> Option<String> {
1201+
let mut searcher = Self::new(decl_pos);
1202+
let _ = searchable.search(&mut searcher);
1203+
searcher.result
1204+
}
1205+
}
1206+
1207+
impl Searcher for FormatDeclaration {
1208+
fn search_decl(&mut self, pos: &SrcPos, decl: FoundDeclaration) -> SearchState {
1209+
if pos == &self.decl_pos {
1210+
self.result = Some(match decl {
1211+
FoundDeclaration::InterfaceObject(ref value) => match value.list_type {
1212+
InterfaceListType::Port => format!("```vhdl\nport {};\n```", value),
1213+
InterfaceListType::Generic => format!("```vhdl\ngeneric {};\n```", value),
1214+
InterfaceListType::Parameter => format!("```vhdl\n{};\n```", value),
1215+
},
1216+
FoundDeclaration::ForIndex(ref ident, ref drange) => {
1217+
format!("```vhdl\nfor {} in {} loop\n```", ident, drange)
1218+
}
1219+
FoundDeclaration::ForGenerateIndex(ref ident, ref value) => match ident {
1220+
Some(ident) => format!("```vhdl\n{}: {}\n```", ident, value),
1221+
None => format!("```vhdl\n{}\n```", value),
1222+
},
1223+
FoundDeclaration::Library(ref value) => {
1224+
format!("```vhdl\nlibrary {};\n```", value)
1225+
}
1226+
FoundDeclaration::Function(ref value) => {
1227+
format!("```vhdl\n{};\n```", value)
1228+
}
1229+
FoundDeclaration::Procedure(ref value) => {
1230+
format!("```vhdl\n{};\n```", value)
1231+
}
1232+
FoundDeclaration::Object(ref value) => {
1233+
format!("```vhdl\n{}\n```", value)
1234+
}
1235+
FoundDeclaration::File(ref value) => {
1236+
format!("```vhdl\n{}\n```", value)
1237+
}
1238+
FoundDeclaration::Type(ref value) => {
1239+
format!("```vhdl\n{}\n```", value)
1240+
}
1241+
FoundDeclaration::Component(ref value) => {
1242+
format!("```vhdl\n{}\n```", value)
1243+
}
1244+
FoundDeclaration::Alias(ref value) => {
1245+
format!("```vhdl\n{}\n```", value)
1246+
}
1247+
FoundDeclaration::Package(ref value) => {
1248+
format!("```vhdl\n{}\n```", value)
1249+
}
1250+
FoundDeclaration::PackageInstance(ref value) => {
1251+
format!("```vhdl\n{}\n```", value)
1252+
}
1253+
FoundDeclaration::Configuration(ref value) => {
1254+
format!("```vhdl\n{}\n```", value)
1255+
}
1256+
FoundDeclaration::Entity(ref value) => {
1257+
format!("```vhdl\n{}\n```", value)
1258+
}
1259+
FoundDeclaration::Context(ref value) => {
1260+
format!("```vhdl\n{}\n```", value)
1261+
}
1262+
});
1263+
Finished(Found)
1264+
} else {
1265+
NotFinished
1266+
}
1267+
}
1268+
}
1269+
1270+
// Search for all references to declaration/definition
11121271
pub struct FindAllReferences {
11131272
decl_pos: SrcPos,
11141273
references: Vec<SrcPos>,

0 commit comments

Comments
 (0)