forked from chipsalliance/verible
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhover.cc
190 lines (172 loc) · 6.33 KB
/
hover.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2023 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "verilog/tools/ls/hover.h"
#include <memory>
#include <optional>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "common/lsp/lsp-protocol.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/concrete_syntax_tree.h"
#include "common/text/symbol.h"
#include "common/text/token_info.h"
#include "common/text/tree_context_visitor.h"
#include "common/text/tree_utils.h"
#include "common/util/casts.h"
#include "common/util/range.h"
#include "verilog/CST/seq_block.h"
#include "verilog/CST/verilog_nonterminals.h"
#include "verilog/analysis/symbol_table.h"
#include "verilog/parser/verilog_token_enum.h"
#include "verilog/tools/ls/lsp-parse-buffer.h"
#include "verilog/tools/ls/symbol-table-handler.h"
namespace verilog {
namespace {
using verible::Symbol;
using verible::SyntaxTreeLeaf;
using verible::SyntaxTreeNode;
using verible::TreeContextVisitor;
// Finds names/labels of named blocks
class FindBeginLabel : public TreeContextVisitor {
public:
// Performs search of the label for end entry, based on its location in
// string and tags
absl::string_view LabelSearch(const verible::ConcreteSyntaxTree &tree,
absl::string_view substring, NodeEnum endtag,
NodeEnum begintag) {
substring_ = substring;
begintag_ = begintag;
endtag_ = endtag;
substring_found_ = false;
finished_ = false;
tree->Accept(this);
return label_;
}
private:
void Visit(const SyntaxTreeLeaf &leaf) final {
if (verible::IsSubRange(leaf.get().text(), substring_)) {
substring_found_ = true;
}
}
void Visit(const SyntaxTreeNode &node) final {
if (finished_) return;
const std::unique_ptr<Symbol> *lastbegin = nullptr;
for (const std::unique_ptr<Symbol> &child : node.children()) {
if (!child) continue;
if (child->Kind() == verible::SymbolKind::kLeaf &&
node.Tag().tag == static_cast<int>(endtag_)) {
Visit(verible::down_cast<const SyntaxTreeLeaf &>(*child));
if (substring_found_) return;
} else if (child->Tag().tag == static_cast<int>(begintag_)) {
lastbegin = &child;
} else if (child->Kind() == verible::SymbolKind::kNode) {
Visit(verible::down_cast<const SyntaxTreeNode &>(*child));
if (!label_.empty()) return;
if (substring_found_) {
if (!lastbegin) {
finished_ = true;
return;
}
const verible::TokenInfo *info = GetBeginLabelTokenInfo(**lastbegin);
finished_ = true;
if (!info) return;
label_ = info->text();
return;
}
}
if (finished_) return;
}
}
absl::string_view substring_;
NodeEnum endtag_;
NodeEnum begintag_;
absl::string_view label_;
bool substring_found_;
bool finished_;
};
// Constructs a Hover message for the given location
class HoverBuilder {
public:
HoverBuilder(SymbolTableHandler *symbol_table_handler,
const BufferTrackerContainer &tracker_container,
const verible::lsp::HoverParams ¶ms)
: symbol_table_handler_(symbol_table_handler),
tracker_container_(tracker_container),
params_(params) {}
verible::lsp::Hover Build() {
std::optional<verible::TokenInfo> token =
symbol_table_handler_->GetTokenAtTextDocumentPosition(
params_, tracker_container_);
if (!token) return {};
verible::lsp::Hover response;
switch (token->token_enum()) {
case verilog_tokentype::TK_end:
HoverInfoEndToken(&response, *token);
break;
default:
HoverInfoIdentifier(&response, *token);
}
return response;
}
private:
void HoverInfoEndToken(verible::lsp::Hover *response,
const verible::TokenInfo &token) {
const verilog::BufferTracker *tracker =
tracker_container_.FindBufferTrackerOrNull(params_.textDocument.uri);
if (!tracker) return;
std::shared_ptr<const ParsedBuffer> parsedbuffer = tracker->current();
if (!parsedbuffer) return;
const verible::ConcreteSyntaxTree &tree =
parsedbuffer->parser().SyntaxTree();
if (!tree) return;
FindBeginLabel search;
absl::string_view label = search.LabelSearch(
tree, token.text(), NodeEnum::kEnd, NodeEnum::kBegin);
if (label.empty()) return;
response->contents.value = "### End of block\n\n";
absl::StrAppend(&response->contents.value, "---\n\nName: ", label,
"\n\n---");
}
void HoverInfoIdentifier(verible::lsp::Hover *response,
const verible::TokenInfo &token) {
absl::string_view symbol = token.text();
const SymbolTableNode *node =
symbol_table_handler_->FindDefinitionNode(symbol);
if (!node) return;
const SymbolInfo &info = node->Value();
response->contents.value = absl::StrCat(
"### ", SymbolMetaTypeAsString(info.metatype), " ", symbol, "\n\n");
if (!info.declared_type.syntax_origin && info.declared_type.implicit) {
absl::StrAppend(&response->contents.value,
"---\n\nType: (implicit)\n\n---");
} else if (info.declared_type.syntax_origin) {
absl::StrAppend(
&response->contents.value, "---\n\n", "Type: ",
verible::StringSpanOfSymbol(*info.declared_type.syntax_origin),
"\n\n---");
}
}
SymbolTableHandler *symbol_table_handler_;
const BufferTrackerContainer &tracker_container_;
const verible::lsp::HoverParams ¶ms_;
};
} // namespace
verible::lsp::Hover CreateHoverInformation(
SymbolTableHandler *symbol_table_handler,
const BufferTrackerContainer &tracker, const verible::lsp::HoverParams &p) {
HoverBuilder builder(symbol_table_handler, tracker, p);
return builder.Build();
}
} // namespace verilog