-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement textDocument/hover request.
Rebased from PR #1922 This will implement the method, but currently it is not offered yet in the initialization to the editor; to be enabled once tests finished. The implementation requires a global symbol table, which is potentially a bit heavy. We might need to introduce the concept of a per-file symbol table for faster local lookups.
- Loading branch information
1 parent
0f97047
commit 2d1dd11
Showing
9 changed files
with
379 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// 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. | ||
// | ||
|
||
#ifndef VERILOG_TOOLS_LS_HOVER_H_INCLUDED | ||
#define VERILOG_TOOLS_LS_HOVER_H_INCLUDED | ||
|
||
#include "common/lsp/lsp-protocol.h" | ||
#include "verilog/tools/ls/lsp-parse-buffer.h" | ||
#include "verilog/tools/ls/symbol-table-handler.h" | ||
|
||
namespace verilog { | ||
// Provides hover information for given location | ||
verible::lsp::Hover CreateHoverInformation( | ||
SymbolTableHandler *symbol_table_handler, | ||
const BufferTrackerContainer &tracker, const verible::lsp::HoverParams &p); | ||
} // namespace verilog | ||
|
||
#endif // hover_h_INCLUDED |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.