mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
LSP rename
This commit is contained in:
@@ -44,7 +44,6 @@ public:
|
||||
/// Changes the source identified by the LSP client path _uri to _text.
|
||||
void setSourceByUri(std::string const& _uri, std::string _text);
|
||||
|
||||
void addOrUpdateFile(boost::filesystem::path const& _path, frontend::SourceCode _source);
|
||||
void setSourceUnits(StringMap _sources);
|
||||
frontend::ReadCallback::Result readFile(std::string const& _kind, std::string const& _sourceUnitName);
|
||||
frontend::ReadCallback::Callback reader()
|
||||
|
||||
@@ -45,8 +45,8 @@ public:
|
||||
/// from the JSON-RPC parameters.
|
||||
std::pair<std::string, langutil::LineColumn> extractSourceUnitNameAndLineColumn(Json::Value const& _params) const;
|
||||
|
||||
langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.charStreamProvider(); }
|
||||
FileRepository const& fileRepository() const noexcept { return m_server.fileRepository(); }
|
||||
langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_server.compilerStack(); }
|
||||
FileRepository& fileRepository() const noexcept { return m_server.fileRepository(); }
|
||||
Transport& client() const noexcept { return m_server.client(); }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
// LSP feature implementations
|
||||
#include <libsolidity/lsp/GotoDefinition.h>
|
||||
#include <libsolidity/lsp/RenameSymbol.h>
|
||||
#include <libsolidity/lsp/SemanticTokensBuilder.h>
|
||||
|
||||
#include <liblangutil/SourceReferenceExtractor.h>
|
||||
@@ -124,6 +125,7 @@ LanguageServer::LanguageServer(Transport& _transport):
|
||||
{"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
|
||||
{"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
|
||||
{"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
|
||||
{"textDocument/rename", RenameSymbol(*this) },
|
||||
{"textDocument/implementation", GotoDefinition(*this) },
|
||||
{"textDocument/semanticTokens/full", bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
|
||||
{"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
|
||||
@@ -314,6 +316,8 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
|
||||
replyArgs["capabilities"]["semanticTokensProvider"]["legend"] = semanticTokensLegend();
|
||||
replyArgs["capabilities"]["semanticTokensProvider"]["range"] = false;
|
||||
replyArgs["capabilities"]["semanticTokensProvider"]["full"] = true; // XOR requests.full.delta = true
|
||||
replyArgs["capabilities"]["renameProvider"] = true;
|
||||
|
||||
|
||||
m_client.reply(_id, move(replyArgs));
|
||||
}
|
||||
@@ -432,6 +436,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
|
||||
compileAndUpdateDiagnostics();
|
||||
}
|
||||
|
||||
|
||||
ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
||||
{
|
||||
if (m_compilerStack.state() < CompilerStack::AnalysisPerformed)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
namespace solidity::lsp
|
||||
{
|
||||
|
||||
class RenameSymbol;
|
||||
enum class ErrorCode;
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ public:
|
||||
FileRepository& fileRepository() noexcept { return m_fileRepository; }
|
||||
Transport& client() noexcept { return m_client; }
|
||||
frontend::ASTNode const* astNodeAtSourceLocation(std::string const& _sourceUnitName, langutil::LineColumn const& _filePos);
|
||||
langutil::CharStreamProvider const& charStreamProvider() const noexcept { return m_compilerStack; }
|
||||
frontend::CompilerStack const& compilerStack() const noexcept { return m_compilerStack; }
|
||||
|
||||
private:
|
||||
/// Checks if the server is initialized (to be used by messages that need it to be initialized).
|
||||
@@ -72,6 +73,7 @@ private:
|
||||
void handleTextDocumentDidOpen(Json::Value const& _args);
|
||||
void handleTextDocumentDidChange(Json::Value const& _args);
|
||||
void handleTextDocumentDidClose(Json::Value const& _args);
|
||||
void handleRename(Json::Value const& _args);
|
||||
void handleGotoDefinition(MessageID _id, Json::Value const& _args);
|
||||
void semanticTokensFull(MessageID _id, Json::Value const& _args);
|
||||
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#include <libsolidity/lsp/RenameSymbol.h>
|
||||
#include <libsolidity/lsp/Utils.h>
|
||||
|
||||
#include <libyul/AST.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace solidity::frontend;
|
||||
using namespace solidity::langutil;
|
||||
using namespace solidity::lsp;
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _functionCall)
|
||||
{
|
||||
if (
|
||||
auto const* functionType = dynamic_cast<FunctionType const*>(_functionCall.expression().annotation().type);
|
||||
functionType && functionType->hasDeclaration()
|
||||
)
|
||||
if (auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(&functionType->declaration()))
|
||||
return functionDefinition;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
||||
{
|
||||
auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
|
||||
string const newName = _args["newName"].asString();
|
||||
string const uri = _args["textDocument"]["uri"].asString();
|
||||
|
||||
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
|
||||
|
||||
m_symbolName = {};
|
||||
m_declarationToRename = nullptr;
|
||||
m_sourceUnits = { &m_server.compilerStack().ast(sourceUnitName) };
|
||||
m_locations.clear();
|
||||
|
||||
optional<int> cursorBytePosition = charStreamProvider()
|
||||
.charStream(sourceUnitName)
|
||||
.translateLineColumnToPosition(lineColumn);
|
||||
solAssert(cursorBytePosition.has_value(), "Expected source pos");
|
||||
|
||||
extractNameAndDeclaration(*sourceNode, *cursorBytePosition);
|
||||
|
||||
// Find all source units using this symbol
|
||||
for (auto const& [name, content]: fileRepository().sourceUnits())
|
||||
{
|
||||
auto const& sourceUnit = m_server.compilerStack().ast(name);
|
||||
for (auto const* referencedSourceUnit: sourceUnit.referencedSourceUnits(true, util::convertContainer<set<SourceUnit const*>>(m_sourceUnits)))
|
||||
if (*referencedSourceUnit->location().sourceName == sourceUnitName)
|
||||
{
|
||||
m_sourceUnits.insert(&sourceUnit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Origin source unit should always be checked
|
||||
m_sourceUnits.insert(&m_declarationToRename->sourceUnit());
|
||||
|
||||
Visitor visitor(*this);
|
||||
|
||||
for (auto const* sourceUnit: m_sourceUnits)
|
||||
sourceUnit->accept(visitor);
|
||||
|
||||
// Apply changes in reverse order (will iterate in reverse)
|
||||
sort(m_locations.begin(), m_locations.end());
|
||||
|
||||
Json::Value reply = Json::objectValue;
|
||||
reply["changes"] = Json::objectValue;
|
||||
|
||||
Json::Value edits = Json::arrayValue;
|
||||
|
||||
for (auto i = m_locations.rbegin(); i != m_locations.rend(); i++)
|
||||
{
|
||||
solAssert(i->isValid());
|
||||
|
||||
// Replace in our file repository
|
||||
string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
|
||||
string buffer = fileRepository().sourceUnits().at(*i->sourceName);
|
||||
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
|
||||
fileRepository().setSourceByUri(uri, std::move(buffer));
|
||||
|
||||
Json::Value edit = Json::objectValue;
|
||||
edit["range"] = toRange(*i);
|
||||
edit["newText"] = newName;
|
||||
|
||||
// Record changes for the client
|
||||
edits.append(edit);
|
||||
if (i + 1 == m_locations.rend() || (i + 1)->sourceName != i->sourceName)
|
||||
{
|
||||
reply["changes"][uri] = edits;
|
||||
edits = Json::arrayValue;
|
||||
}
|
||||
}
|
||||
|
||||
client().reply(_id, reply);
|
||||
}
|
||||
|
||||
void RenameSymbol::extractNameAndDeclaration(ASTNode const& _node, int _cursorBytePosition)
|
||||
{
|
||||
// Identify symbol name and node
|
||||
if (auto const* declaration = dynamic_cast<Declaration const*>(&_node))
|
||||
{
|
||||
if (declaration->nameLocation().containsOffset(_cursorBytePosition))
|
||||
{
|
||||
m_symbolName = declaration->name();
|
||||
m_declarationToRename = declaration;
|
||||
}
|
||||
else if (auto const* importDirective = dynamic_cast<ImportDirective const*>(declaration))
|
||||
extractNameAndDeclaration(*importDirective, _cursorBytePosition);
|
||||
}
|
||||
else if (auto const* identifier = dynamic_cast<Identifier const*>(&_node))
|
||||
{
|
||||
if (auto const* declReference = dynamic_cast<Declaration const*>(identifier->annotation().referencedDeclaration))
|
||||
{
|
||||
m_symbolName = identifier->name();
|
||||
m_declarationToRename = declReference;
|
||||
}
|
||||
}
|
||||
else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(&_node))
|
||||
extractNameAndDeclaration(*identifierPath, _cursorBytePosition);
|
||||
else if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_node))
|
||||
{
|
||||
m_symbolName = memberAccess->memberName();
|
||||
m_declarationToRename = memberAccess->annotation().referencedDeclaration;
|
||||
}
|
||||
else if (auto const* functionCall = dynamic_cast<FunctionCall const*>(&_node))
|
||||
extractNameAndDeclaration(*functionCall, _cursorBytePosition);
|
||||
else if (auto const* inlineAssembly = dynamic_cast<InlineAssembly const*>(&_node))
|
||||
extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition);
|
||||
else
|
||||
solAssert(false, "Unexpected ASTNODE id: " + to_string(_node.id()));
|
||||
|
||||
lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end));
|
||||
}
|
||||
|
||||
void RenameSymbol::extractNameAndDeclaration(ImportDirective const& _importDirective, int _cursorBytePosition)
|
||||
{
|
||||
for (ImportDirective::SymbolAlias const& symbolAlias: _importDirective.symbolAliases())
|
||||
if (symbolAlias.location.containsOffset(_cursorBytePosition))
|
||||
{
|
||||
solAssert(symbolAlias.alias);
|
||||
m_symbolName = *symbolAlias.alias;
|
||||
m_declarationToRename = symbolAlias.symbol->annotation().referencedDeclaration;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(ImportDirective const& _node)
|
||||
{
|
||||
// Handles SourceUnit aliases
|
||||
if (handleGenericDeclaration(_node))
|
||||
return;
|
||||
|
||||
for (ImportDirective::SymbolAlias const& symbolAlias: _node.symbolAliases())
|
||||
if (
|
||||
symbolAlias.alias != nullptr &&
|
||||
*symbolAlias.alias == m_outer.m_symbolName &&
|
||||
symbolAlias.symbol->annotation().referencedDeclaration == m_outer.m_declarationToRename
|
||||
)
|
||||
m_outer.m_locations.emplace_back(symbolAlias.location);
|
||||
}
|
||||
|
||||
void RenameSymbol::extractNameAndDeclaration(FunctionCall const& _functionCall, int _cursorBytePosition)
|
||||
{
|
||||
if (auto const* functionDefinition = extractCallableDeclaration(_functionCall))
|
||||
for (size_t i = 0; i < _functionCall.names().size(); i++)
|
||||
if (_functionCall.nameLocations()[i].containsOffset(_cursorBytePosition))
|
||||
{
|
||||
m_symbolName = *_functionCall.names()[i];
|
||||
for (size_t j = 0; j < functionDefinition->parameters().size(); j++)
|
||||
if (
|
||||
functionDefinition->parameters()[j] &&
|
||||
functionDefinition->parameters()[j]->name() == m_symbolName
|
||||
)
|
||||
m_declarationToRename = functionDefinition->parameters()[j].get();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(FunctionCall const& _node)
|
||||
{
|
||||
SourceLocation nameLocationInFunctionCall;
|
||||
|
||||
for (size_t i = 0; i < _node.names().size(); i++)
|
||||
if (_node.names()[i] && *_node.names()[i] == m_outer.m_symbolName)
|
||||
nameLocationInFunctionCall = _node.nameLocations()[i];
|
||||
|
||||
if (!nameLocationInFunctionCall.isValid())
|
||||
return;
|
||||
|
||||
if (auto const* functionDefinition = extractCallableDeclaration(_node))
|
||||
for (size_t j = 0; j < functionDefinition->parameters().size(); j++)
|
||||
if (
|
||||
functionDefinition->parameters()[j] &&
|
||||
*functionDefinition->parameters()[j] == *m_outer.m_declarationToRename
|
||||
)
|
||||
m_outer.m_locations.emplace_back(nameLocationInFunctionCall);
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(MemberAccess const& _node)
|
||||
{
|
||||
if (
|
||||
m_outer.m_symbolName == _node.memberName() &&
|
||||
*m_outer.m_declarationToRename == *_node.annotation().referencedDeclaration
|
||||
)
|
||||
m_outer.m_locations.emplace_back(_node.memberLocation());
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(Identifier const& _node)
|
||||
{
|
||||
if (
|
||||
m_outer.m_symbolName == _node.name() &&
|
||||
*m_outer.m_declarationToRename == *_node.annotation().referencedDeclaration
|
||||
)
|
||||
m_outer.m_locations.emplace_back(_node.location());
|
||||
}
|
||||
|
||||
void RenameSymbol::extractNameAndDeclaration(IdentifierPath const& _identifierPath, int _cursorBytePosition)
|
||||
{
|
||||
// iterate through the elements of the path to find the one the cursor is on
|
||||
size_t numIdentifiers = _identifierPath.pathLocations().size();
|
||||
for (size_t i = 0; i < numIdentifiers; i++)
|
||||
{
|
||||
auto& location = _identifierPath.pathLocations()[i];
|
||||
|
||||
if (location.containsOffset(_cursorBytePosition))
|
||||
{
|
||||
solAssert(_identifierPath.annotation().pathDeclarations.size() == numIdentifiers);
|
||||
solAssert(_identifierPath.path().size() == numIdentifiers);
|
||||
|
||||
m_declarationToRename = _identifierPath.annotation().pathDeclarations[i];
|
||||
m_symbolName = _identifierPath.path()[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(IdentifierPath const& _node)
|
||||
{
|
||||
std::vector<Declaration const*>& declarations = _node.annotation().pathDeclarations;
|
||||
solAssert(declarations.size() == _node.path().size());
|
||||
|
||||
for (size_t i = 0; i < _node.path().size(); i++)
|
||||
if (
|
||||
_node.path()[i] == m_outer.m_symbolName &&
|
||||
declarations[i] == m_outer.m_declarationToRename
|
||||
)
|
||||
m_outer.m_locations.emplace_back(_node.pathLocations()[i]);
|
||||
}
|
||||
|
||||
void RenameSymbol::extractNameAndDeclaration(InlineAssembly const& _inlineAssembly, int _cursorBytePosition)
|
||||
{
|
||||
for (auto&& [identifier, externalReference]: _inlineAssembly.annotation().externalReferences)
|
||||
{
|
||||
SourceLocation location = yul::nativeLocationOf(*identifier);
|
||||
location.end -= static_cast<int>(externalReference.suffix.size() + 1);
|
||||
|
||||
if (location.containsOffset(_cursorBytePosition))
|
||||
{
|
||||
m_declarationToRename = externalReference.declaration;
|
||||
m_symbolName = identifier->name.str();
|
||||
|
||||
if (!externalReference.suffix.empty())
|
||||
m_symbolName = m_symbolName.substr(0, m_symbolName.length() - externalReference.suffix.size() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node)
|
||||
{
|
||||
for (auto&& [identifier, externalReference]: _node.annotation().externalReferences)
|
||||
{
|
||||
string identifierName = identifier->name.str();
|
||||
if (!externalReference.suffix.empty())
|
||||
identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1);
|
||||
|
||||
if (
|
||||
externalReference.declaration == m_outer.m_declarationToRename &&
|
||||
identifierName == m_outer.m_symbolName
|
||||
)
|
||||
{
|
||||
SourceLocation location = yul::nativeLocationOf(*identifier);
|
||||
location.end -= static_cast<int>(externalReference.suffix.size() + 1);
|
||||
|
||||
m_outer.m_locations.emplace_back(location);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
This file is part of solidity.
|
||||
|
||||
solidity is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
solidity is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
#include <libsolidity/lsp/HandlerBase.h>
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/ASTVisitor.h>
|
||||
|
||||
namespace solidity::lsp
|
||||
{
|
||||
|
||||
class RenameSymbol: public HandlerBase
|
||||
{
|
||||
public:
|
||||
explicit RenameSymbol(LanguageServer& _server): HandlerBase(_server) {}
|
||||
|
||||
void operator()(MessageID, Json::Value const&);
|
||||
protected:
|
||||
// Nested class because otherwise `RenameSymbol` couldn't be easily used
|
||||
// with LanguageServer::m_handlers as `ASTConstVisitor` deletes required
|
||||
// c'tors
|
||||
struct Visitor: public frontend::ASTConstVisitor
|
||||
{
|
||||
explicit Visitor(RenameSymbol& _outer): m_outer(_outer) {}
|
||||
void endVisit(frontend::ImportDirective const& _node) override;
|
||||
void endVisit(frontend::MemberAccess const& _node) override;
|
||||
void endVisit(frontend::Identifier const& _node) override;
|
||||
void endVisit(frontend::IdentifierPath const& _node) override;
|
||||
void endVisit(frontend::FunctionCall const& _node) override;
|
||||
void endVisit(frontend::InlineAssembly const& _node) override;
|
||||
|
||||
void endVisit(frontend::ContractDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::StructDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::EnumDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::EnumValue const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::UserDefinedValueTypeDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::VariableDeclaration const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::FunctionDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::ModifierDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::EventDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
void endVisit(frontend::ErrorDefinition const& _node) override
|
||||
{
|
||||
handleGenericDeclaration(_node);
|
||||
}
|
||||
|
||||
bool handleGenericDeclaration(frontend::Declaration const& _declaration)
|
||||
{
|
||||
if (
|
||||
m_outer.m_symbolName == _declaration.name() &&
|
||||
*m_outer.m_declarationToRename == _declaration
|
||||
)
|
||||
{
|
||||
m_outer.m_locations.emplace_back(_declaration.nameLocation());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
RenameSymbol& m_outer;
|
||||
};
|
||||
|
||||
void extractNameAndDeclaration(frontend::ASTNode const& _node, int _cursorBytePosition);
|
||||
void extractNameAndDeclaration(frontend::IdentifierPath const& _identifierPath, int _cursorBytePosition);
|
||||
void extractNameAndDeclaration(frontend::ImportDirective const& _importDirective, int _cursorBytePosition);
|
||||
void extractNameAndDeclaration(frontend::FunctionCall const& _functionCall, int _cursorBytePosition);
|
||||
void extractNameAndDeclaration(frontend::InlineAssembly const& _inlineAssembly, int _cursorBytePosition);
|
||||
|
||||
// Node to rename
|
||||
frontend::Declaration const* m_declarationToRename = nullptr;
|
||||
// Original name
|
||||
frontend::ASTString m_symbolName = {};
|
||||
// SourceUnits to search & replace symbol in
|
||||
std::set<frontend::SourceUnit const*, frontend::ASTNode::CompareByID> m_sourceUnits = {};
|
||||
// Source locations that need to be replaced
|
||||
std::vector<langutil::SourceLocation> m_locations = {};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -195,7 +195,7 @@ void SemanticTokensBuilder::endVisit(frontend::StructuredDocumentation const& _d
|
||||
|
||||
void SemanticTokensBuilder::endVisit(frontend::Identifier const& _identifier)
|
||||
{
|
||||
lspDebug(fmt::format("Identifier: {}, {}..{} cat={}", _identifier.name(), _identifier.location().start, _identifier.location().end, _identifier.annotation().type->category()));
|
||||
//lspDebug(fmt::format("Identifier: {}, {}..{} cat={}", _identifier.name(), _identifier.location().start, _identifier.location().end, _identifier.annotation().type->category()));
|
||||
|
||||
SemanticTokenModifiers modifiers = SemanticTokenModifiers::None;
|
||||
if (_identifier.annotation().isConstant.set() && *_identifier.annotation().isConstant)
|
||||
|
||||
Reference in New Issue
Block a user