Applying final review

This commit is contained in:
Christian Parpart 2022-09-28 15:48:49 +02:00
parent 6884d2f516
commit 02e84ea547
3 changed files with 41 additions and 35 deletions

View File

@ -548,7 +548,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
} }
tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, langutil::LineColumn const& _filePos) tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
{ {
if (m_compilerStack.state() < CompilerStack::AnalysisPerformed) if (m_compilerStack.state() < CompilerStack::AnalysisPerformed)
return {nullptr, -1}; return {nullptr, -1};

View File

@ -35,23 +35,23 @@ namespace solidity::lsp
ReferenceCollector::ReferenceCollector( ReferenceCollector::ReferenceCollector(
Declaration const& _declaration, Declaration const& _declaration,
string const& _sourceIdentifierName string const& _identifierAtCursorLocation
): ):
m_declaration{_declaration}, m_declaration{_declaration},
m_sourceIdentifierName{_sourceIdentifierName.empty() ? _declaration.name() : _sourceIdentifierName} m_identifierAtCursorLocation{_identifierAtCursorLocation.empty() ? _declaration.name() : _identifierAtCursorLocation}
{ {
} }
vector<Reference> ReferenceCollector::collect( vector<Reference> ReferenceCollector::collect(
Declaration const* _declaration, Declaration const* _declaration,
ASTNode const& _astSearchRoot, ASTNode const& _astSearchRoot,
string const& _sourceIdentifierName string const& _identifierAtCursorLocation
) )
{ {
if (!_declaration) if (!_declaration)
return {}; return {};
ReferenceCollector collector(*_declaration, _sourceIdentifierName); ReferenceCollector collector(*_declaration, _identifierAtCursorLocation);
_astSearchRoot.accept(collector); _astSearchRoot.accept(collector);
return std::move(collector.m_collectedReferences); return std::move(collector.m_collectedReferences);
} }
@ -65,10 +65,10 @@ vector<Reference> ReferenceCollector::collect(
if (!_sourceNode) if (!_sourceNode)
return {}; return {};
auto references = vector<Reference>{}; solAssert(_sourceNode->location().containsOffset(_sourceOffset), "");
if (auto const* identifier = dynamic_cast<Identifier const*>(_sourceNode)) if (auto const* identifier = dynamic_cast<Identifier const*>(_sourceNode))
references += collect(identifier->annotation().referencedDeclaration, _sourceUnit, identifier->name()); return collect(identifier->annotation().referencedDeclaration, _sourceUnit, identifier->name());
else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(_sourceNode)) else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(_sourceNode))
{ {
solAssert(identifierPath->path().size() >= 1, ""); solAssert(identifierPath->path().size() >= 1, "");
@ -79,19 +79,17 @@ vector<Reference> ReferenceCollector::collect(
{ {
Declaration const* declaration = identifierPath->annotation().pathDeclarations.at(i); Declaration const* declaration = identifierPath->annotation().pathDeclarations.at(i);
ASTString const& name = identifierPath->path().at(i); ASTString const& name = identifierPath->path().at(i);
references += collect(declaration, _sourceUnit, name); return collect(declaration, _sourceUnit, name);
break;
} }
} }
return {};
} }
else if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(_sourceNode)) else if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(_sourceNode))
references += collect(memberAccess->annotation().referencedDeclaration, _sourceUnit, memberAccess->memberName()); return collect(memberAccess->annotation().referencedDeclaration, _sourceUnit, memberAccess->memberName());
else if (auto const* declaration = dynamic_cast<Declaration const*>(_sourceNode)) else if (auto const* declaration = dynamic_cast<Declaration const*>(_sourceNode))
references += collect(declaration, _sourceUnit, declaration->name()); return collect(declaration, _sourceUnit, declaration->name());
else else
lspRequire(false, ErrorCode::InternalError, "Unhandled AST node "s + typeid(*_sourceNode).name()); lspRequire(false, ErrorCode::InternalError, "Unhandled AST node "s + typeid(*_sourceNode).name());
return references;
} }
bool ReferenceCollector::visit(ImportDirective const& _import) bool ReferenceCollector::visit(ImportDirective const& _import)
@ -99,7 +97,7 @@ bool ReferenceCollector::visit(ImportDirective const& _import)
for (ImportDirective::SymbolAlias const& symbolAlias: _import.symbolAliases()) for (ImportDirective::SymbolAlias const& symbolAlias: _import.symbolAliases())
{ {
if ( if (
symbolAlias.alias && *symbolAlias.alias == m_sourceIdentifierName && symbolAlias.alias && *symbolAlias.alias == m_identifierAtCursorLocation &&
symbolAlias.symbol && symbolAlias.symbol->annotation().referencedDeclaration == &m_declaration symbolAlias.symbol && symbolAlias.symbol->annotation().referencedDeclaration == &m_declaration
) )
m_collectedReferences.emplace_back(symbolAlias.location, DocumentHighlightKind::Read); m_collectedReferences.emplace_back(symbolAlias.location, DocumentHighlightKind::Read);
@ -122,7 +120,7 @@ void ReferenceCollector::endVisit(IdentifierPath const& _identifierPath)
_identifierPath.annotation().pathDeclarations.at(i) : _identifierPath.annotation().pathDeclarations.at(i) :
nullptr; nullptr;
if (declaration == &m_declaration && name == m_sourceIdentifierName) if (declaration == &m_declaration && name == m_identifierAtCursorLocation)
m_collectedReferences.emplace_back(_identifierPath.pathLocations().at(i), m_kind); m_collectedReferences.emplace_back(_identifierPath.pathLocations().at(i), m_kind);
} }
} }
@ -148,7 +146,7 @@ bool ReferenceCollector::visit(Assignment const& _assignment)
bool ReferenceCollector::visit(VariableDeclaration const& _variableDeclaration) bool ReferenceCollector::visit(VariableDeclaration const& _variableDeclaration)
{ {
if (&_variableDeclaration == &m_declaration && _variableDeclaration.name() == m_sourceIdentifierName) if (&_variableDeclaration == &m_declaration && _variableDeclaration.name() == m_identifierAtCursorLocation)
m_collectedReferences.emplace_back(_variableDeclaration.nameLocation(), DocumentHighlightKind::Write); m_collectedReferences.emplace_back(_variableDeclaration.nameLocation(), DocumentHighlightKind::Write);
return true; return true;
} }
@ -158,7 +156,7 @@ bool ReferenceCollector::visitNode(ASTNode const& _genericNode)
if (&_genericNode == &m_declaration) if (&_genericNode == &m_declaration)
{ {
Declaration const* declaration = dynamic_cast<Declaration const*>(&_genericNode); Declaration const* declaration = dynamic_cast<Declaration const*>(&_genericNode);
if (declaration->name() == m_sourceIdentifierName) if (declaration->name() == m_identifierAtCursorLocation)
m_collectedReferences.emplace_back(declaration->nameLocation(), m_kind); m_collectedReferences.emplace_back(declaration->nameLocation(), m_kind);
} }

View File

@ -24,6 +24,8 @@ namespace solidity::lsp
{ {
/** /**
* Describes the way a reference to be highlighted is used in the code.
*
* See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#documentHighlightKind * See https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#documentHighlightKind
*/ */
enum class DocumentHighlightKind enum class DocumentHighlightKind
@ -41,31 +43,19 @@ using Reference = std::tuple<langutil::SourceLocation, DocumentHighlightKind>;
/** /**
* ReferenceCollector can be used to collect all source locations and their usage * ReferenceCollector can be used to collect all source locations and their usage
* of a given symbol in the AST tree. * of a given symbol in the AST.
*/ */
class ReferenceCollector: public frontend::ASTConstVisitor class ReferenceCollector: public frontend::ASTConstVisitor
{ {
private: public:
ReferenceCollector(frontend::Declaration const& _declaration, std::string const& _sourceIdentifierName = ""); /// Collects all references (symbols with the same matching declaration as @p _sourceNode) in the given source unit.
/// Collects all occurrences of a given identifier matching the same declaration.
/// Just passing the AST node and infer the name from there is not enough as they might have been aliased.
/// ///
/// @param _declaration the declaration to match against for the symbols to collect /// @param _sourceNode AST node to start collecting recursively down from.
/// @param _sourceOffset byte offset into the respective file reflecting the exact location of the cursor /// @param _sourceOffset byte offset into the respective file reflecting the exact location of the cursor
/// @param _astSearchRoot the AST base root node to start the recursive traversal to collect the references /// @param _sourceUnit the related source unit the given AST node belongs to.
/// @param _sourceIdentifierName the symbolic name that must match, which is explicitly given as it might have been altered due to aliases.
/// ///
/// @returns a vector of Reference objects that contain the source location of each match as well as their /// @returns a vector of Reference objects that contain the source location of each match as well as their
/// semantic use (e.g. read access or write access). /// semantic use (e.g. read access or write access).
static std::vector<Reference> collect(
frontend::Declaration const* _declaration,
frontend::ASTNode const& _astSearchRoot,
std::string const& _sourceIdentifierName
);
public:
/// Collects all references (symbols with the same matching declaration as @p _sourceNode) in the given source unit.
static std::vector<Reference> collect(frontend::ASTNode const* _sourceNode, int _sourceOffset, frontend::SourceUnit const& _sourceUnit); static std::vector<Reference> collect(frontend::ASTNode const* _sourceNode, int _sourceOffset, frontend::SourceUnit const& _sourceUnit);
bool visit(frontend::ImportDirective const& _import) override; bool visit(frontend::ImportDirective const& _import) override;
@ -76,9 +66,27 @@ public:
bool visit(frontend::VariableDeclaration const& _node) override; bool visit(frontend::VariableDeclaration const& _node) override;
bool visitNode(frontend::ASTNode const& _node) override; bool visitNode(frontend::ASTNode const& _node) override;
private:
ReferenceCollector(frontend::Declaration const& _declaration, std::string const& _identifierAtCursorLocation = "");
/// Collects all occurrences of a given identifier matching the same declaration.
/// Just passing the AST node and inferring the name from there is not enough as they might have been aliased.
///
/// @param _declaration the declaration to match against for the symbols to collect
/// @param _astSearchRoot the AST base root node to start the recursive traversal to collect the references
/// @param _identifierAtCursorLocation the symbolic name that must match, which is explicitly given as it might have been altered due to aliases.
///
/// @returns a vector of Reference objects that contain the source location of each match as well as their
/// semantic use (e.g. read access or write access).
static std::vector<Reference> collect(
frontend::Declaration const* _declaration,
frontend::ASTNode const& _astSearchRoot,
std::string const& _identifierAtCursorLocation
);
private: private:
frontend::Declaration const& m_declaration; frontend::Declaration const& m_declaration;
std::string const& m_sourceIdentifierName; std::string const& m_identifierAtCursorLocation;
std::vector<Reference> m_collectedReferences; std::vector<Reference> m_collectedReferences;
DocumentHighlightKind m_kind = DocumentHighlightKind::Read; DocumentHighlightKind m_kind = DocumentHighlightKind::Read;
}; };