mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #14493 from ethereum/purge-using-namespace-from-libsolidity-lsp-parsing
Purge using namespace from libsolidity/lsp and parsing
This commit is contained in:
commit
25fc3aa32f
@ -1859,7 +1859,7 @@ Json::Value CompilerStack::gasEstimates(std::string const& _contractName) const
|
|||||||
if (contract.fallbackFunction())
|
if (contract.fallbackFunction())
|
||||||
/// This needs to be set to an invalid signature in order to trigger the fallback,
|
/// This needs to be set to an invalid signature in order to trigger the fallback,
|
||||||
/// without the shortcut (of CALLDATSIZE == 0), and therefore to receive the upper bound.
|
/// without the shortcut (of CALLDATSIZE == 0), and therefore to receive the upper bound.
|
||||||
/// An empty std::string ("") would work to trigger the shortcut only.
|
/// An empty string ("") would work to trigger the shortcut only.
|
||||||
externalFunctions[""] = gasToJson(gasEstimator.functionalEstimation(*items, "INVALID"));
|
externalFunctions[""] = gasToJson(gasEstimator.functionalEstimation(*items, "INVALID"));
|
||||||
|
|
||||||
if (!externalFunctions.empty())
|
if (!externalFunctions.empty())
|
||||||
|
@ -323,7 +323,7 @@ Json::Value formatLinkReferences(std::map<size_t, std::string> const& linkRefere
|
|||||||
std::string const& fullname = ref.second;
|
std::string const& fullname = ref.second;
|
||||||
|
|
||||||
// If the link reference does not contain a colon, assume that the file name is missing and
|
// If the link reference does not contain a colon, assume that the file name is missing and
|
||||||
// the whole std::string represents the library name.
|
// the whole string represents the library name.
|
||||||
size_t colon = fullname.rfind(':');
|
size_t colon = fullname.rfind(':');
|
||||||
std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : "");
|
std::string file = (colon != std::string::npos ? fullname.substr(0, colon) : "");
|
||||||
std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname);
|
std::string name = (colon != std::string::npos ? fullname.substr(colon + 1) : fullname);
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
|
|
||||||
namespace solidity::lsp
|
namespace solidity::lsp
|
||||||
{
|
{
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
@ -35,16 +32,16 @@ namespace
|
|||||||
|
|
||||||
struct MarkdownBuilder
|
struct MarkdownBuilder
|
||||||
{
|
{
|
||||||
stringstream result;
|
std::stringstream result;
|
||||||
|
|
||||||
MarkdownBuilder& solidityCode(string const& _code)
|
MarkdownBuilder& solidityCode(std::string const& _code)
|
||||||
{
|
{
|
||||||
auto constexpr SolidityLanguageId = "solidity";
|
auto constexpr SolidityLanguageId = "solidity";
|
||||||
result << "```" << SolidityLanguageId << '\n' << _code << "\n```\n\n";
|
result << "```" << SolidityLanguageId << '\n' << _code << "\n```\n\n";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkdownBuilder& paragraph(string const& _text)
|
MarkdownBuilder& paragraph(std::string const& _text)
|
||||||
{
|
{
|
||||||
if (!_text.empty())
|
if (!_text.empty())
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
@ -54,11 +53,11 @@ void FileRepository::setIncludePaths(std::vector<boost::filesystem::path> _paths
|
|||||||
m_includePaths = std::move(_paths);
|
m_includePaths = std::move(_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
string FileRepository::sourceUnitNameToUri(string const& _sourceUnitName) const
|
std::string FileRepository::sourceUnitNameToUri(std::string const& _sourceUnitName) const
|
||||||
{
|
{
|
||||||
regex const windowsDriveLetterPath("^[a-zA-Z]:/");
|
std::regex const windowsDriveLetterPath("^[a-zA-Z]:/");
|
||||||
|
|
||||||
auto const ensurePathIsUnixLike = [&](string inputPath) -> string {
|
auto const ensurePathIsUnixLike = [&](std::string inputPath) -> std::string {
|
||||||
if (!regex_search(inputPath, windowsDriveLetterPath))
|
if (!regex_search(inputPath, windowsDriveLetterPath))
|
||||||
return inputPath;
|
return inputPath;
|
||||||
else
|
else
|
||||||
@ -86,13 +85,13 @@ string FileRepository::sourceUnitNameToUri(string const& _sourceUnitName) const
|
|||||||
return "file:///" + _sourceUnitName;
|
return "file:///" + _sourceUnitName;
|
||||||
}
|
}
|
||||||
|
|
||||||
string FileRepository::uriToSourceUnitName(string const& _path) const
|
std::string FileRepository::uriToSourceUnitName(std::string const& _path) const
|
||||||
{
|
{
|
||||||
lspRequire(boost::algorithm::starts_with(_path, "file://"), ErrorCode::InternalError, "URI must start with file://");
|
lspRequire(boost::algorithm::starts_with(_path, "file://"), ErrorCode::InternalError, "URI must start with file://");
|
||||||
return stripFileUriSchemePrefix(_path);
|
return stripFileUriSchemePrefix(_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileRepository::setSourceByUri(string const& _uri, string _source)
|
void FileRepository::setSourceByUri(std::string const& _uri, std::string _source)
|
||||||
{
|
{
|
||||||
// This is needed for uris outside the base path. It can lead to collisions,
|
// This is needed for uris outside the base path. It can lead to collisions,
|
||||||
// but we need to mostly rewrite this in a future version anyway.
|
// but we need to mostly rewrite this in a future version anyway.
|
||||||
@ -110,9 +109,9 @@ Result<boost::filesystem::path> FileRepository::tryResolvePath(std::string const
|
|||||||
)
|
)
|
||||||
return boost::filesystem::path(_strippedSourceUnitName);
|
return boost::filesystem::path(_strippedSourceUnitName);
|
||||||
|
|
||||||
vector<boost::filesystem::path> candidates;
|
std::vector<boost::filesystem::path> candidates;
|
||||||
vector<reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath};
|
std::vector<std::reference_wrapper<boost::filesystem::path const>> prefixes = {m_basePath};
|
||||||
prefixes += (m_includePaths | ranges::to<vector<reference_wrapper<boost::filesystem::path const>>>);
|
prefixes += (m_includePaths | ranges::to<std::vector<std::reference_wrapper<boost::filesystem::path const>>>);
|
||||||
auto const defaultInclude = m_basePath / "node_modules";
|
auto const defaultInclude = m_basePath / "node_modules";
|
||||||
if (m_includePaths.empty())
|
if (m_includePaths.empty())
|
||||||
prefixes.emplace_back(defaultInclude);
|
prefixes.emplace_back(defaultInclude);
|
||||||
@ -148,7 +147,7 @@ Result<boost::filesystem::path> FileRepository::tryResolvePath(std::string const
|
|||||||
return candidates[0];
|
return candidates[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend::ReadCallback::Result FileRepository::readFile(string const& _kind, string const& _sourceUnitName)
|
frontend::ReadCallback::Result FileRepository::readFile(std::string const& _kind, std::string const& _sourceUnitName)
|
||||||
{
|
{
|
||||||
solAssert(
|
solAssert(
|
||||||
_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile),
|
_kind == ReadCallback::kindString(ReadCallback::Kind::ReadFile),
|
||||||
@ -161,7 +160,7 @@ frontend::ReadCallback::Result FileRepository::readFile(string const& _kind, str
|
|||||||
if (m_sourceCodes.count(_sourceUnitName))
|
if (m_sourceCodes.count(_sourceUnitName))
|
||||||
return ReadCallback::Result{true, m_sourceCodes.at(_sourceUnitName)};
|
return ReadCallback::Result{true, m_sourceCodes.at(_sourceUnitName)};
|
||||||
|
|
||||||
string const strippedSourceUnitName = stripFileUriSchemePrefix(_sourceUnitName);
|
std::string const strippedSourceUnitName = stripFileUriSchemePrefix(_sourceUnitName);
|
||||||
Result<boost::filesystem::path> const resolvedPath = tryResolvePath(strippedSourceUnitName);
|
Result<boost::filesystem::path> const resolvedPath = tryResolvePath(strippedSourceUnitName);
|
||||||
if (!resolvedPath.message().empty())
|
if (!resolvedPath.message().empty())
|
||||||
return ReadCallback::Result{false, resolvedPath.message()};
|
return ReadCallback::Result{false, resolvedPath.message()};
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
|
void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
|
||||||
{
|
{
|
||||||
@ -38,7 +37,7 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
|
|||||||
|
|
||||||
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
|
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
|
||||||
|
|
||||||
vector<SourceLocation> locations;
|
std::vector<SourceLocation> locations;
|
||||||
if (auto const* expression = dynamic_cast<Expression const*>(sourceNode))
|
if (auto const* expression = dynamic_cast<Expression const*>(sourceNode))
|
||||||
{
|
{
|
||||||
// Handles all expressions that can have one or more declaration annotation.
|
// Handles all expressions that can have one or more declaration annotation.
|
||||||
@ -56,7 +55,7 @@ void GotoDefinition::operator()(MessageID _id, Json::Value const& _args)
|
|||||||
{
|
{
|
||||||
auto const& path = *importDirective->annotation().absolutePath;
|
auto const& path = *importDirective->annotation().absolutePath;
|
||||||
if (fileRepository().sourceUnits().count(path))
|
if (fileRepository().sourceUnits().count(path))
|
||||||
locations.emplace_back(SourceLocation{0, 0, make_shared<string const>(path)});
|
locations.emplace_back(SourceLocation{0, 0, std::make_shared<std::string const>(path)});
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value reply = Json::arrayValue;
|
Json::Value reply = Json::arrayValue;
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
Json::Value HandlerBase::toRange(SourceLocation const& _location) const
|
Json::Value HandlerBase::toRange(SourceLocation const& _location) const
|
||||||
{
|
{
|
||||||
@ -52,10 +51,10 @@ Json::Value HandlerBase::toJson(SourceLocation const& _location) const
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const
|
std::pair<std::string, LineColumn> HandlerBase::extractSourceUnitNameAndLineColumn(Json::Value const& _args) const
|
||||||
{
|
{
|
||||||
string const uri = _args["textDocument"]["uri"].asString();
|
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||||
string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
|
std::string const sourceUnitName = fileRepository().uriToSourceUnitName(uri);
|
||||||
if (!fileRepository().sourceUnits().count(sourceUnitName))
|
if (!fileRepository().sourceUnits().count(sourceUnitName))
|
||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
RequestError(ErrorCode::RequestFailed) <<
|
RequestError(ErrorCode::RequestFailed) <<
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
@ -109,7 +108,7 @@ Json::Value semanticTokensLegend()
|
|||||||
tokenTypes.append("operator");
|
tokenTypes.append("operator");
|
||||||
tokenTypes.append("parameter");
|
tokenTypes.append("parameter");
|
||||||
tokenTypes.append("property");
|
tokenTypes.append("property");
|
||||||
tokenTypes.append("string");
|
tokenTypes.append("std::string");
|
||||||
tokenTypes.append("struct");
|
tokenTypes.append("struct");
|
||||||
tokenTypes.append("type");
|
tokenTypes.append("type");
|
||||||
tokenTypes.append("typeParameter");
|
tokenTypes.append("typeParameter");
|
||||||
@ -137,19 +136,19 @@ LanguageServer::LanguageServer(Transport& _transport):
|
|||||||
{"$/cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
|
{"$/cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
|
||||||
{"cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
|
{"cancelRequest", [](auto, auto) {/*nothing for now as we are synchronous */}},
|
||||||
{"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }},
|
{"exit", [this](auto, auto) { m_state = (m_state == State::ShutdownRequested ? State::ExitRequested : State::ExitWithoutShutdown); }},
|
||||||
{"initialize", bind(&LanguageServer::handleInitialize, this, _1, _2)},
|
{"initialize", std::bind(&LanguageServer::handleInitialize, this, _1, _2)},
|
||||||
{"initialized", bind(&LanguageServer::handleInitialized, this, _1, _2)},
|
{"initialized", std::bind(&LanguageServer::handleInitialized, this, _1, _2)},
|
||||||
{"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }},
|
{"$/setTrace", [this](auto, Json::Value const& args) { setTrace(args["value"]); }},
|
||||||
{"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }},
|
{"shutdown", [this](auto, auto) { m_state = State::ShutdownRequested; }},
|
||||||
{"textDocument/definition", GotoDefinition(*this) },
|
{"textDocument/definition", GotoDefinition(*this) },
|
||||||
{"textDocument/didOpen", bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
|
{"textDocument/didOpen", std::bind(&LanguageServer::handleTextDocumentDidOpen, this, _2)},
|
||||||
{"textDocument/didChange", bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
|
{"textDocument/didChange", std::bind(&LanguageServer::handleTextDocumentDidChange, this, _2)},
|
||||||
{"textDocument/didClose", bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
|
{"textDocument/didClose", std::bind(&LanguageServer::handleTextDocumentDidClose, this, _2)},
|
||||||
{"textDocument/hover", DocumentHoverHandler(*this) },
|
{"textDocument/hover", DocumentHoverHandler(*this) },
|
||||||
{"textDocument/rename", RenameSymbol(*this) },
|
{"textDocument/rename", RenameSymbol(*this) },
|
||||||
{"textDocument/implementation", GotoDefinition(*this) },
|
{"textDocument/implementation", GotoDefinition(*this) },
|
||||||
{"textDocument/semanticTokens/full", bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
|
{"textDocument/semanticTokens/full", std::bind(&LanguageServer::semanticTokensFull, this, _1, _2)},
|
||||||
{"workspace/didChangeConfiguration", bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
|
{"workspace/didChangeConfiguration", std::bind(&LanguageServer::handleWorkspaceDidChangeConfiguration, this, _2)},
|
||||||
},
|
},
|
||||||
m_fileRepository("/" /* basePath */, {} /* no search paths */),
|
m_fileRepository("/" /* basePath */, {} /* no search paths */),
|
||||||
m_compilerStack{m_fileRepository.reader()}
|
m_compilerStack{m_fileRepository.reader()}
|
||||||
@ -196,7 +195,7 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
|
|||||||
int typeFailureCount = 0;
|
int typeFailureCount = 0;
|
||||||
if (jsonIncludePaths.isArray())
|
if (jsonIncludePaths.isArray())
|
||||||
{
|
{
|
||||||
vector<boost::filesystem::path> includePaths;
|
std::vector<boost::filesystem::path> includePaths;
|
||||||
for (Json::Value const& jsonPath: jsonIncludePaths)
|
for (Json::Value const& jsonPath: jsonIncludePaths)
|
||||||
{
|
{
|
||||||
if (jsonPath.isString())
|
if (jsonPath.isString())
|
||||||
@ -214,9 +213,9 @@ void LanguageServer::changeConfiguration(Json::Value const& _settings)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<boost::filesystem::path> LanguageServer::allSolidityFilesFromProject() const
|
std::vector<boost::filesystem::path> LanguageServer::allSolidityFilesFromProject() const
|
||||||
{
|
{
|
||||||
vector<fs::path> collectedPaths{};
|
std::vector<fs::path> collectedPaths{};
|
||||||
|
|
||||||
// We explicitly decided against including all files from include paths but leave the possibility
|
// We explicitly decided against including all files from include paths but leave the possibility
|
||||||
// open for a future PR to enable such a feature to be optionally enabled (default disabled).
|
// open for a future PR to enable such a feature to be optionally enabled (default disabled).
|
||||||
@ -242,7 +241,7 @@ void LanguageServer::compile()
|
|||||||
// so we just remove all non-open files.
|
// so we just remove all non-open files.
|
||||||
|
|
||||||
FileRepository oldRepository(m_fileRepository.basePath(), m_fileRepository.includePaths());
|
FileRepository oldRepository(m_fileRepository.basePath(), m_fileRepository.includePaths());
|
||||||
swap(oldRepository, m_fileRepository);
|
std::swap(oldRepository, m_fileRepository);
|
||||||
|
|
||||||
// Load all solidity files from project.
|
// Load all solidity files from project.
|
||||||
if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory)
|
if (m_fileLoadStrategy == FileLoadStrategy::ProjectDirectory)
|
||||||
@ -256,7 +255,7 @@ void LanguageServer::compile()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Overwrite all files as opened by the client, including the ones which might potentially have changes.
|
// Overwrite all files as opened by the client, including the ones which might potentially have changes.
|
||||||
for (string const& fileName: m_openFiles)
|
for (std::string const& fileName: m_openFiles)
|
||||||
m_fileRepository.setSourceByUri(
|
m_fileRepository.setSourceByUri(
|
||||||
fileName,
|
fileName,
|
||||||
oldRepository.sourceUnits().at(oldRepository.uriToSourceUnitName(fileName))
|
oldRepository.sourceUnits().at(oldRepository.uriToSourceUnitName(fileName))
|
||||||
@ -275,13 +274,13 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
|||||||
|
|
||||||
// These are the source units we will sent diagnostics to the client for sure,
|
// These are the source units we will sent diagnostics to the client for sure,
|
||||||
// even if it is just to clear previous diagnostics.
|
// even if it is just to clear previous diagnostics.
|
||||||
map<string, Json::Value> diagnosticsBySourceUnit;
|
std::map<std::string, Json::Value> diagnosticsBySourceUnit;
|
||||||
for (string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
|
for (std::string const& sourceUnitName: m_fileRepository.sourceUnits() | ranges::views::keys)
|
||||||
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
|
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
|
||||||
for (string const& sourceUnitName: m_nonemptyDiagnostics)
|
for (std::string const& sourceUnitName: m_nonemptyDiagnostics)
|
||||||
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
|
diagnosticsBySourceUnit[sourceUnitName] = Json::arrayValue;
|
||||||
|
|
||||||
for (shared_ptr<Error const> const& error: m_compilerStack.errors())
|
for (std::shared_ptr<Error const> const& error: m_compilerStack.errors())
|
||||||
{
|
{
|
||||||
SourceLocation const* location = error->sourceLocation();
|
SourceLocation const* location = error->sourceLocation();
|
||||||
if (!location || !location->sourceName)
|
if (!location || !location->sourceName)
|
||||||
@ -292,8 +291,8 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
|||||||
jsonDiag["source"] = "solc";
|
jsonDiag["source"] = "solc";
|
||||||
jsonDiag["severity"] = toDiagnosticSeverity(error->type());
|
jsonDiag["severity"] = toDiagnosticSeverity(error->type());
|
||||||
jsonDiag["code"] = Json::UInt64{error->errorId().error};
|
jsonDiag["code"] = Json::UInt64{error->errorId().error};
|
||||||
string message = Error::formatErrorType(error->type()) + ":";
|
std::string message = Error::formatErrorType(error->type()) + ":";
|
||||||
if (string const* comment = error->comment())
|
if (std::string const* comment = error->comment())
|
||||||
message += " " + *comment;
|
message += " " + *comment;
|
||||||
jsonDiag["message"] = std::move(message);
|
jsonDiag["message"] = std::move(message);
|
||||||
jsonDiag["range"] = toRange(*location);
|
jsonDiag["range"] = toRange(*location);
|
||||||
@ -314,7 +313,7 @@ void LanguageServer::compileAndUpdateDiagnostics()
|
|||||||
{
|
{
|
||||||
Json::Value extra;
|
Json::Value extra;
|
||||||
extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size());
|
extra["openFileCount"] = Json::UInt64(diagnosticsBySourceUnit.size());
|
||||||
m_client.trace("Number of currently open files: " + to_string(diagnosticsBySourceUnit.size()), extra);
|
m_client.trace("Number of currently open files: " + std::to_string(diagnosticsBySourceUnit.size()), extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nonemptyDiagnostics.clear();
|
m_nonemptyDiagnostics.clear();
|
||||||
@ -336,13 +335,13 @@ bool LanguageServer::run()
|
|||||||
MessageID id;
|
MessageID id;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
optional<Json::Value> const jsonMessage = m_client.receive();
|
std::optional<Json::Value> const jsonMessage = m_client.receive();
|
||||||
if (!jsonMessage)
|
if (!jsonMessage)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((*jsonMessage)["method"].isString())
|
if ((*jsonMessage)["method"].isString())
|
||||||
{
|
{
|
||||||
string const methodName = (*jsonMessage)["method"].asString();
|
std::string const methodName = (*jsonMessage)["method"].asString();
|
||||||
id = (*jsonMessage)["id"];
|
id = (*jsonMessage)["id"];
|
||||||
lspDebug(fmt::format("received method call: {}", methodName));
|
lspDebug(fmt::format("received method call: {}", methodName));
|
||||||
|
|
||||||
@ -391,7 +390,7 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
|
|||||||
|
|
||||||
// The default of FileReader is to use `.`, but the path from where the LSP was started
|
// The default of FileReader is to use `.`, but the path from where the LSP was started
|
||||||
// should not matter.
|
// should not matter.
|
||||||
string rootPath("/");
|
std::string rootPath("/");
|
||||||
if (Json::Value uri = _args["rootUri"])
|
if (Json::Value uri = _args["rootUri"])
|
||||||
{
|
{
|
||||||
rootPath = uri.asString();
|
rootPath = uri.asString();
|
||||||
@ -414,7 +413,7 @@ void LanguageServer::handleInitialize(MessageID _id, Json::Value const& _args)
|
|||||||
|
|
||||||
Json::Value replyArgs;
|
Json::Value replyArgs;
|
||||||
replyArgs["serverInfo"]["name"] = "solc";
|
replyArgs["serverInfo"]["name"] = "solc";
|
||||||
replyArgs["serverInfo"]["version"] = string(VersionNumber);
|
replyArgs["serverInfo"]["version"] = std::string(VersionNumber);
|
||||||
replyArgs["capabilities"]["definitionProvider"] = true;
|
replyArgs["capabilities"]["definitionProvider"] = true;
|
||||||
replyArgs["capabilities"]["implementationProvider"] = true;
|
replyArgs["capabilities"]["implementationProvider"] = true;
|
||||||
replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental
|
replyArgs["capabilities"]["textDocumentSync"]["change"] = 2; // 0=none, 1=full, 2=incremental
|
||||||
@ -440,7 +439,7 @@ void LanguageServer::semanticTokensFull(MessageID _id, Json::Value const& _args)
|
|||||||
|
|
||||||
compile();
|
compile();
|
||||||
|
|
||||||
auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<string>());
|
auto const sourceName = m_fileRepository.uriToSourceUnitName(uri.as<std::string>());
|
||||||
SourceUnit const& ast = m_compilerStack.ast(sourceName);
|
SourceUnit const& ast = m_compilerStack.ast(sourceName);
|
||||||
m_compilerStack.charStream(sourceName);
|
m_compilerStack.charStream(sourceName);
|
||||||
Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName));
|
Json::Value data = SemanticTokensBuilder().build(ast, m_compilerStack.charStream(sourceName));
|
||||||
@ -465,7 +464,7 @@ void LanguageServer::setTrace(Json::Value const& _args)
|
|||||||
// Simply ignore invalid parameter.
|
// Simply ignore invalid parameter.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string const stringValue = _args.asString();
|
std::string const stringValue = _args.asString();
|
||||||
if (stringValue == "off")
|
if (stringValue == "off")
|
||||||
m_client.setTrace(TraceValue::Off);
|
m_client.setTrace(TraceValue::Off);
|
||||||
else if (stringValue == "messages")
|
else if (stringValue == "messages")
|
||||||
@ -484,8 +483,8 @@ void LanguageServer::handleTextDocumentDidOpen(Json::Value const& _args)
|
|||||||
"Text document parameter missing."
|
"Text document parameter missing."
|
||||||
);
|
);
|
||||||
|
|
||||||
string text = _args["textDocument"]["text"].asString();
|
std::string text = _args["textDocument"]["text"].asString();
|
||||||
string uri = _args["textDocument"]["uri"].asString();
|
std::string uri = _args["textDocument"]["uri"].asString();
|
||||||
m_openFiles.insert(uri);
|
m_openFiles.insert(uri);
|
||||||
m_fileRepository.setSourceByUri(uri, std::move(text));
|
m_fileRepository.setSourceByUri(uri, std::move(text));
|
||||||
compileAndUpdateDiagnostics();
|
compileAndUpdateDiagnostics();
|
||||||
@ -495,7 +494,7 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
|
|||||||
{
|
{
|
||||||
requireServerInitialized();
|
requireServerInitialized();
|
||||||
|
|
||||||
string const uri = _args["textDocument"]["uri"].asString();
|
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||||
|
|
||||||
for (Json::Value jsonContentChange: _args["contentChanges"])
|
for (Json::Value jsonContentChange: _args["contentChanges"])
|
||||||
{
|
{
|
||||||
@ -505,24 +504,24 @@ void LanguageServer::handleTextDocumentDidChange(Json::Value const& _args)
|
|||||||
"Invalid content reference."
|
"Invalid content reference."
|
||||||
);
|
);
|
||||||
|
|
||||||
string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri);
|
std::string const sourceUnitName = m_fileRepository.uriToSourceUnitName(uri);
|
||||||
lspRequire(
|
lspRequire(
|
||||||
m_fileRepository.sourceUnits().count(sourceUnitName),
|
m_fileRepository.sourceUnits().count(sourceUnitName),
|
||||||
ErrorCode::RequestFailed,
|
ErrorCode::RequestFailed,
|
||||||
"Unknown file: " + uri
|
"Unknown file: " + uri
|
||||||
);
|
);
|
||||||
|
|
||||||
string text = jsonContentChange["text"].asString();
|
std::string text = jsonContentChange["text"].asString();
|
||||||
if (jsonContentChange["range"].isObject()) // otherwise full content update
|
if (jsonContentChange["range"].isObject()) // otherwise full content update
|
||||||
{
|
{
|
||||||
optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]);
|
std::optional<SourceLocation> change = parseRange(m_fileRepository, sourceUnitName, jsonContentChange["range"]);
|
||||||
lspRequire(
|
lspRequire(
|
||||||
change && change->hasText(),
|
change && change->hasText(),
|
||||||
ErrorCode::RequestFailed,
|
ErrorCode::RequestFailed,
|
||||||
"Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"])
|
"Invalid source range: " + util::jsonCompactPrint(jsonContentChange["range"])
|
||||||
);
|
);
|
||||||
|
|
||||||
string buffer = m_fileRepository.sourceUnits().at(sourceUnitName);
|
std::string buffer = m_fileRepository.sourceUnits().at(sourceUnitName);
|
||||||
buffer.replace(static_cast<size_t>(change->start), static_cast<size_t>(change->end - change->start), std::move(text));
|
buffer.replace(static_cast<size_t>(change->start), static_cast<size_t>(change->end - change->start), std::move(text));
|
||||||
text = std::move(buffer);
|
text = std::move(buffer);
|
||||||
}
|
}
|
||||||
@ -542,7 +541,7 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
|
|||||||
"Text document parameter missing."
|
"Text document parameter missing."
|
||||||
);
|
);
|
||||||
|
|
||||||
string uri = _args["textDocument"]["uri"].asString();
|
std::string uri = _args["textDocument"]["uri"].asString();
|
||||||
m_openFiles.erase(uri);
|
m_openFiles.erase(uri);
|
||||||
|
|
||||||
compileAndUpdateDiagnostics();
|
compileAndUpdateDiagnostics();
|
||||||
@ -550,17 +549,17 @@ void LanguageServer::handleTextDocumentDidClose(Json::Value const& _args)
|
|||||||
|
|
||||||
ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
ASTNode const* LanguageServer::astNodeAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
||||||
{
|
{
|
||||||
return get<ASTNode const*>(astNodeAndOffsetAtSourceLocation(_sourceUnitName, _filePos));
|
return std::get<ASTNode const*>(astNodeAndOffsetAtSourceLocation(_sourceUnitName, _filePos));
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<ASTNode const*, int> LanguageServer::astNodeAndOffsetAtSourceLocation(std::string const& _sourceUnitName, LineColumn const& _filePos)
|
std::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};
|
||||||
if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
|
if (!m_fileRepository.sourceUnits().count(_sourceUnitName))
|
||||||
return {nullptr, -1};
|
return {nullptr, -1};
|
||||||
|
|
||||||
optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos);
|
std::optional<int> sourcePos = m_compilerStack.charStream(_sourceUnitName).translateLineColumnToPosition(_filePos);
|
||||||
if (!sourcePos)
|
if (!sourcePos)
|
||||||
return {nullptr, -1};
|
return {nullptr, -1};
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -51,8 +50,8 @@ CallableDeclaration const* extractCallableDeclaration(FunctionCall const& _funct
|
|||||||
void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
||||||
{
|
{
|
||||||
auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
|
auto const&& [sourceUnitName, lineColumn] = extractSourceUnitNameAndLineColumn(_args);
|
||||||
string const newName = _args["newName"].asString();
|
std::string const newName = _args["newName"].asString();
|
||||||
string const uri = _args["textDocument"]["uri"].asString();
|
std::string const uri = _args["textDocument"]["uri"].asString();
|
||||||
|
|
||||||
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
|
ASTNode const* sourceNode = m_server.astNodeAtSourceLocation(sourceUnitName, lineColumn);
|
||||||
|
|
||||||
@ -61,7 +60,7 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
|||||||
m_sourceUnits = { &m_server.compilerStack().ast(sourceUnitName) };
|
m_sourceUnits = { &m_server.compilerStack().ast(sourceUnitName) };
|
||||||
m_locations.clear();
|
m_locations.clear();
|
||||||
|
|
||||||
optional<int> cursorBytePosition = charStreamProvider()
|
std::optional<int> cursorBytePosition = charStreamProvider()
|
||||||
.charStream(sourceUnitName)
|
.charStream(sourceUnitName)
|
||||||
.translateLineColumnToPosition(lineColumn);
|
.translateLineColumnToPosition(lineColumn);
|
||||||
solAssert(cursorBytePosition.has_value(), "Expected source pos");
|
solAssert(cursorBytePosition.has_value(), "Expected source pos");
|
||||||
@ -72,7 +71,7 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
|||||||
for (auto const& [name, content]: fileRepository().sourceUnits())
|
for (auto const& [name, content]: fileRepository().sourceUnits())
|
||||||
{
|
{
|
||||||
auto const& sourceUnit = m_server.compilerStack().ast(name);
|
auto const& sourceUnit = m_server.compilerStack().ast(name);
|
||||||
for (auto const* referencedSourceUnit: sourceUnit.referencedSourceUnits(true, util::convertContainer<set<SourceUnit const*>>(m_sourceUnits)))
|
for (auto const* referencedSourceUnit: sourceUnit.referencedSourceUnits(true, util::convertContainer<std::set<SourceUnit const*>>(m_sourceUnits)))
|
||||||
if (*referencedSourceUnit->location().sourceName == sourceUnitName)
|
if (*referencedSourceUnit->location().sourceName == sourceUnitName)
|
||||||
{
|
{
|
||||||
m_sourceUnits.insert(&sourceUnit);
|
m_sourceUnits.insert(&sourceUnit);
|
||||||
@ -101,8 +100,8 @@ void RenameSymbol::operator()(MessageID _id, Json::Value const& _args)
|
|||||||
solAssert(i->isValid());
|
solAssert(i->isValid());
|
||||||
|
|
||||||
// Replace in our file repository
|
// Replace in our file repository
|
||||||
string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
|
std::string const uri = fileRepository().sourceUnitNameToUri(*i->sourceName);
|
||||||
string buffer = fileRepository().sourceUnits().at(*i->sourceName);
|
std::string buffer = fileRepository().sourceUnits().at(*i->sourceName);
|
||||||
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
|
buffer.replace((size_t)i->start, (size_t)(i->end - i->start), newName);
|
||||||
fileRepository().setSourceByUri(uri, std::move(buffer));
|
fileRepository().setSourceByUri(uri, std::move(buffer));
|
||||||
|
|
||||||
@ -155,7 +154,7 @@ void RenameSymbol::extractNameAndDeclaration(ASTNode const& _node, int _cursorBy
|
|||||||
else if (auto const* inlineAssembly = dynamic_cast<InlineAssembly const*>(&_node))
|
else if (auto const* inlineAssembly = dynamic_cast<InlineAssembly const*>(&_node))
|
||||||
extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition);
|
extractNameAndDeclaration(*inlineAssembly, _cursorBytePosition);
|
||||||
else
|
else
|
||||||
solAssert(false, "Unexpected ASTNODE id: " + to_string(_node.id()));
|
solAssert(false, "Unexpected ASTNODE id: " + std::to_string(_node.id()));
|
||||||
|
|
||||||
lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end));
|
lspDebug(fmt::format("Goal: rename '{}', loc: {}-{}", m_symbolName, m_declarationToRename->nameLocation().start, m_declarationToRename->nameLocation().end));
|
||||||
}
|
}
|
||||||
@ -297,7 +296,7 @@ void RenameSymbol::Visitor::endVisit(InlineAssembly const& _node)
|
|||||||
{
|
{
|
||||||
for (auto&& [identifier, externalReference]: _node.annotation().externalReferences)
|
for (auto&& [identifier, externalReference]: _node.annotation().externalReferences)
|
||||||
{
|
{
|
||||||
string identifierName = identifier->name.str();
|
std::string identifierName = identifier->name.str();
|
||||||
if (!externalReference.suffix.empty())
|
if (!externalReference.suffix.empty())
|
||||||
identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1);
|
identifierName = identifierName.substr(0, identifierName.length() - externalReference.suffix.size() - 1);
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
|
|
||||||
@ -33,10 +32,10 @@ namespace solidity::lsp
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type)
|
std::optional<SemanticTokenType> semanticTokenTypeForType(frontend::Type const* _type)
|
||||||
{
|
{
|
||||||
if (!_type)
|
if (!_type)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
switch (_type->category())
|
switch (_type->category())
|
||||||
{
|
{
|
||||||
|
@ -37,34 +37,33 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity::lsp;
|
using namespace solidity::lsp;
|
||||||
|
|
||||||
// {{{ Transport
|
// {{{ Transport
|
||||||
optional<Json::Value> Transport::receive()
|
std::optional<Json::Value> Transport::receive()
|
||||||
{
|
{
|
||||||
auto const headers = parseHeaders();
|
auto const headers = parseHeaders();
|
||||||
if (!headers)
|
if (!headers)
|
||||||
{
|
{
|
||||||
error({}, ErrorCode::ParseError, "Could not parse RPC headers.");
|
error({}, ErrorCode::ParseError, "Could not parse RPC headers.");
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!headers->count("content-length"))
|
if (!headers->count("content-length"))
|
||||||
{
|
{
|
||||||
error({}, ErrorCode::ParseError, "No content-length header found.");
|
error({}, ErrorCode::ParseError, "No content-length header found.");
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
string const data = readBytes(stoul(headers->at("content-length")));
|
std::string const data = readBytes(stoul(headers->at("content-length")));
|
||||||
|
|
||||||
Json::Value jsonMessage;
|
Json::Value jsonMessage;
|
||||||
string jsonParsingErrors;
|
std::string jsonParsingErrors;
|
||||||
solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors);
|
solidity::util::jsonParseStrict(data, jsonMessage, &jsonParsingErrors);
|
||||||
if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject())
|
if (!jsonParsingErrors.empty() || !jsonMessage || !jsonMessage.isObject())
|
||||||
{
|
{
|
||||||
error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors);
|
error({}, ErrorCode::ParseError, "Could not parse RPC JSON payload. " + jsonParsingErrors);
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {std::move(jsonMessage)};
|
return {std::move(jsonMessage)};
|
||||||
@ -82,9 +81,9 @@ void Transport::trace(std::string _message, Json::Value _extra)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<map<string, string>> Transport::parseHeaders()
|
std::optional<std::map<std::string, std::string>> Transport::parseHeaders()
|
||||||
{
|
{
|
||||||
map<string, string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -93,18 +92,18 @@ optional<map<string, string>> Transport::parseHeaders()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
auto const delimiterPos = line.find(':');
|
auto const delimiterPos = line.find(':');
|
||||||
if (delimiterPos == string::npos)
|
if (delimiterPos == std::string::npos)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
auto const name = boost::to_lower_copy(line.substr(0, delimiterPos));
|
auto const name = boost::to_lower_copy(line.substr(0, delimiterPos));
|
||||||
auto const value = line.substr(delimiterPos + 1);
|
auto const value = line.substr(delimiterPos + 1);
|
||||||
if (!headers.emplace(boost::trim_copy(name), boost::trim_copy(value)).second)
|
if (!headers.emplace(boost::trim_copy(name), boost::trim_copy(value)).second)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return {std::move(headers)};
|
return {std::move(headers)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transport::notify(string _method, Json::Value _message)
|
void Transport::notify(std::string _method, Json::Value _message)
|
||||||
{
|
{
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
json["method"] = std::move(_method);
|
json["method"] = std::move(_method);
|
||||||
@ -119,7 +118,7 @@ void Transport::reply(MessageID _id, Json::Value _message)
|
|||||||
send(std::move(json), _id);
|
send(std::move(json), _id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transport::error(MessageID _id, ErrorCode _code, string _message)
|
void Transport::error(MessageID _id, ErrorCode _code, std::string _message)
|
||||||
{
|
{
|
||||||
Json::Value json;
|
Json::Value json;
|
||||||
json["error"]["code"] = static_cast<int>(_code);
|
json["error"]["code"] = static_cast<int>(_code);
|
||||||
@ -135,7 +134,7 @@ void Transport::send(Json::Value _json, MessageID _id)
|
|||||||
_json["id"] = _id;
|
_json["id"] = _id;
|
||||||
|
|
||||||
// Trailing CRLF only for easier readability.
|
// Trailing CRLF only for easier readability.
|
||||||
string const jsonString = solidity::util::jsonCompactPrint(_json);
|
std::string const jsonString = solidity::util::jsonCompactPrint(_json);
|
||||||
|
|
||||||
writeBytes(fmt::format("Content-Length: {}\r\n\r\n", jsonString.size()));
|
writeBytes(fmt::format("Content-Length: {}\r\n\r\n", jsonString.size()));
|
||||||
writeBytes(jsonString);
|
writeBytes(jsonString);
|
||||||
@ -144,7 +143,7 @@ void Transport::send(Json::Value _json, MessageID _id)
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// {{{ IOStreamTransport
|
// {{{ IOStreamTransport
|
||||||
IOStreamTransport::IOStreamTransport(istream& _in, ostream& _out):
|
IOStreamTransport::IOStreamTransport(std::istream& _in, std::ostream& _out):
|
||||||
m_input{_in},
|
m_input{_in},
|
||||||
m_output{_out}
|
m_output{_out}
|
||||||
{
|
{
|
||||||
@ -162,7 +161,7 @@ std::string IOStreamTransport::readBytes(size_t _length)
|
|||||||
|
|
||||||
std::string IOStreamTransport::getline()
|
std::string IOStreamTransport::getline()
|
||||||
{
|
{
|
||||||
string line;
|
std::string line;
|
||||||
std::getline(m_input, line);
|
std::getline(m_input, line);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
@ -30,21 +30,20 @@ namespace solidity::lsp
|
|||||||
|
|
||||||
using namespace frontend;
|
using namespace frontend;
|
||||||
using namespace langutil;
|
using namespace langutil;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
optional<LineColumn> parseLineColumn(Json::Value const& _lineColumn)
|
std::optional<LineColumn> parseLineColumn(Json::Value const& _lineColumn)
|
||||||
{
|
{
|
||||||
if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt())
|
if (_lineColumn.isObject() && _lineColumn["line"].isInt() && _lineColumn["character"].isInt())
|
||||||
return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()};
|
return LineColumn{_lineColumn["line"].asInt(), _lineColumn["character"].asInt()};
|
||||||
else
|
else
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value toJson(LineColumn const& _pos)
|
Json::Value toJson(LineColumn const& _pos)
|
||||||
{
|
{
|
||||||
Json::Value json = Json::objectValue;
|
Json::Value json = Json::objectValue;
|
||||||
json["line"] = max(_pos.line, 0);
|
json["line"] = std::max(_pos.line, 0);
|
||||||
json["character"] = max(_pos.column, 0);
|
json["character"] = std::max(_pos.column, 0);
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@ -70,10 +69,10 @@ Declaration const* referencedDeclaration(Expression const* _expression)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
std::optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
||||||
{
|
{
|
||||||
if (!_declaration)
|
if (!_declaration)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
if (_declaration->nameLocation().isValid())
|
if (_declaration->nameLocation().isValid())
|
||||||
return _declaration->nameLocation();
|
return _declaration->nameLocation();
|
||||||
@ -81,43 +80,43 @@ optional<SourceLocation> declarationLocation(Declaration const* _declaration)
|
|||||||
if (_declaration->location().isValid())
|
if (_declaration->location().isValid())
|
||||||
return _declaration->location();
|
return _declaration->location();
|
||||||
|
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<SourceLocation> parsePosition(
|
std::optional<SourceLocation> parsePosition(
|
||||||
FileRepository const& _fileRepository,
|
FileRepository const& _fileRepository,
|
||||||
string const& _sourceUnitName,
|
std::string const& _sourceUnitName,
|
||||||
Json::Value const& _position
|
Json::Value const& _position
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!_fileRepository.sourceUnits().count(_sourceUnitName))
|
if (!_fileRepository.sourceUnits().count(_sourceUnitName))
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
if (optional<LineColumn> lineColumn = parseLineColumn(_position))
|
if (std::optional<LineColumn> lineColumn = parseLineColumn(_position))
|
||||||
if (optional<int> const offset = CharStream::translateLineColumnToPosition(
|
if (std::optional<int> const offset = CharStream::translateLineColumnToPosition(
|
||||||
_fileRepository.sourceUnits().at(_sourceUnitName),
|
_fileRepository.sourceUnits().at(_sourceUnitName),
|
||||||
*lineColumn
|
*lineColumn
|
||||||
))
|
))
|
||||||
return SourceLocation{*offset, *offset, make_shared<string>(_sourceUnitName)};
|
return SourceLocation{*offset, *offset, std::make_shared<std::string>(_sourceUnitName)};
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<SourceLocation> parseRange(FileRepository const& _fileRepository, string const& _sourceUnitName, Json::Value const& _range)
|
std::optional<SourceLocation> parseRange(FileRepository const& _fileRepository, std::string const& _sourceUnitName, Json::Value const& _range)
|
||||||
{
|
{
|
||||||
if (!_range.isObject())
|
if (!_range.isObject())
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
|
std::optional<SourceLocation> start = parsePosition(_fileRepository, _sourceUnitName, _range["start"]);
|
||||||
optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);
|
std::optional<SourceLocation> end = parsePosition(_fileRepository, _sourceUnitName, _range["end"]);
|
||||||
if (!start || !end)
|
if (!start || !end)
|
||||||
return nullopt;
|
return std::nullopt;
|
||||||
solAssert(*start->sourceName == *end->sourceName);
|
solAssert(*start->sourceName == *end->sourceName);
|
||||||
start->end = end->end;
|
start->end = end->end;
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
string stripFileUriSchemePrefix(string const& _path)
|
std::string stripFileUriSchemePrefix(std::string const& _path)
|
||||||
{
|
{
|
||||||
regex const windowsDriveLetterPath("^file:///[a-zA-Z]:/");
|
std::regex const windowsDriveLetterPath("^file:///[a-zA-Z]:/");
|
||||||
if (regex_search(_path, windowsDriveLetterPath))
|
if (regex_search(_path, windowsDriveLetterPath))
|
||||||
return _path.substr(8);
|
return _path.substr(8);
|
||||||
if (_path.find("file://") == 0)
|
if (_path.find("file://") == 0)
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <range/v3/algorithm/find_if_not.hpp>
|
#include <range/v3/algorithm/find_if_not.hpp>
|
||||||
#include <range/v3/view/subrange.hpp>
|
#include <range/v3/view/subrange.hpp>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
@ -36,17 +35,17 @@ using namespace solidity::frontend;
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
string::const_iterator skipLineOrEOS(
|
std::string::const_iterator skipLineOrEOS(
|
||||||
string::const_iterator _nlPos,
|
std::string::const_iterator _nlPos,
|
||||||
string::const_iterator _end
|
std::string::const_iterator _end
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return (_nlPos == _end) ? _end : ++_nlPos;
|
return (_nlPos == _end) ? _end : ++_nlPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::const_iterator firstNonIdentifier(
|
std::string::const_iterator firstNonIdentifier(
|
||||||
string::const_iterator _pos,
|
std::string::const_iterator _pos,
|
||||||
string::const_iterator _end
|
std::string::const_iterator _end
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto currPos = _pos;
|
auto currPos = _pos;
|
||||||
@ -58,18 +57,18 @@ string::const_iterator firstNonIdentifier(
|
|||||||
return currPos;
|
return currPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::const_iterator firstWhitespaceOrNewline(
|
std::string::const_iterator firstWhitespaceOrNewline(
|
||||||
string::const_iterator _pos,
|
std::string::const_iterator _pos,
|
||||||
string::const_iterator _end
|
std::string::const_iterator _end
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ranges::find_first_of(ranges::make_subrange(_pos, _end), " \t\n");
|
return ranges::find_first_of(ranges::make_subrange(_pos, _end), " \t\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
string::const_iterator skipWhitespace(
|
std::string::const_iterator skipWhitespace(
|
||||||
string::const_iterator _pos,
|
std::string::const_iterator _pos,
|
||||||
string::const_iterator _end
|
std::string::const_iterator _end
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto isWhitespace = [](char const& c) { return (c == ' ' || c == '\t'); };
|
auto isWhitespace = [](char const& c) { return (c == ' ' || c == '\t'); };
|
||||||
@ -78,7 +77,7 @@ string::const_iterator skipWhitespace(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
multimap<string, DocTag> DocStringParser::parse()
|
std::multimap<std::string, DocTag> DocStringParser::parse()
|
||||||
{
|
{
|
||||||
m_lastTag = nullptr;
|
m_lastTag = nullptr;
|
||||||
m_docTags = {};
|
m_docTags = {};
|
||||||
@ -96,7 +95,7 @@ multimap<string, DocTag> DocStringParser::parse()
|
|||||||
{
|
{
|
||||||
// we found a tag
|
// we found a tag
|
||||||
iter tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
|
iter tagNameEndPos = firstWhitespaceOrNewline(tagPos, end);
|
||||||
string tagName{tagPos + 1, tagNameEndPos};
|
std::string tagName{tagPos + 1, tagNameEndPos};
|
||||||
iter tagDataPos = (tagNameEndPos != end) ? tagNameEndPos + 1 : tagNameEndPos;
|
iter tagDataPos = (tagNameEndPos != end) ? tagNameEndPos + 1 : tagNameEndPos;
|
||||||
currPos = parseDocTag(tagDataPos, end, tagName);
|
currPos = parseDocTag(tagDataPos, end, tagName);
|
||||||
}
|
}
|
||||||
@ -141,7 +140,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
|||||||
return _end;
|
return _end;
|
||||||
}
|
}
|
||||||
auto nameEndPos = firstNonIdentifier(nameStartPos, _end);
|
auto nameEndPos = firstNonIdentifier(nameStartPos, _end);
|
||||||
auto paramName = string(nameStartPos, nameEndPos);
|
auto paramName = std::string(nameStartPos, nameEndPos);
|
||||||
|
|
||||||
auto descStartPos = skipWhitespace(nameEndPos, _end);
|
auto descStartPos = skipWhitespace(nameEndPos, _end);
|
||||||
auto nlPos = find(descStartPos, _end, '\n');
|
auto nlPos = find(descStartPos, _end, '\n');
|
||||||
@ -152,7 +151,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
|||||||
return _end;
|
return _end;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto paramDesc = string(descStartPos, nlPos);
|
auto paramDesc = std::string(descStartPos, nlPos);
|
||||||
newTag("param");
|
newTag("param");
|
||||||
m_lastTag->paramName = paramName;
|
m_lastTag->paramName = paramName;
|
||||||
m_lastTag->content = paramDesc;
|
m_lastTag->content = paramDesc;
|
||||||
@ -160,7 +159,7 @@ DocStringParser::iter DocStringParser::parseDocTagParam(iter _pos, iter _end)
|
|||||||
return skipLineOrEOS(nlPos, _end);
|
return skipLineOrEOS(nlPos, _end);
|
||||||
}
|
}
|
||||||
|
|
||||||
DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string const& _tag)
|
DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, std::string const& _tag)
|
||||||
{
|
{
|
||||||
// TODO: need to check for @(start of a tag) between here and the end of line
|
// TODO: need to check for @(start of a tag) between here and the end of line
|
||||||
// for all cases.
|
// for all cases.
|
||||||
@ -178,7 +177,7 @@ DocStringParser::iter DocStringParser::parseDocTag(iter _pos, iter _end, string
|
|||||||
return parseDocTagLine(_pos, _end, true);
|
return parseDocTagLine(_pos, _end, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocStringParser::newTag(string const& _tagName)
|
void DocStringParser::newTag(std::string const& _tagName)
|
||||||
{
|
{
|
||||||
m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second;
|
m_lastTag = &m_docTags.insert(make_pair(_tagName, DocTag()))->second;
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
namespace solidity::frontend
|
namespace solidity::frontend
|
||||||
{
|
{
|
||||||
@ -76,7 +76,7 @@ public:
|
|||||||
solAssert(m_location.sourceName, "");
|
solAssert(m_location.sourceName, "");
|
||||||
if (m_location.end < 0)
|
if (m_location.end < 0)
|
||||||
markEndPosition();
|
markEndPosition();
|
||||||
return make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
|
return std::make_shared<NodeType>(m_parser.nextID(), m_location, std::forward<Args>(_args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation const& location() const noexcept { return m_location; }
|
SourceLocation const& location() const noexcept { return m_location; }
|
||||||
@ -92,11 +92,11 @@ ASTPointer<SourceUnit> Parser::parse(CharStream& _charStream)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_recursionDepth = 0;
|
m_recursionDepth = 0;
|
||||||
m_scanner = make_shared<Scanner>(_charStream);
|
m_scanner = std::make_shared<Scanner>(_charStream);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
m_experimentalSolidityEnabledInCurrentSourceUnit = false;
|
m_experimentalSolidityEnabledInCurrentSourceUnit = false;
|
||||||
|
|
||||||
vector<ASTPointer<ASTNode>> nodes;
|
std::vector<ASTPointer<ASTNode>> nodes;
|
||||||
while (m_scanner->currentToken() == Token::Pragma)
|
while (m_scanner->currentToken() == Token::Pragma)
|
||||||
nodes.push_back(parsePragmaDirective(false));
|
nodes.push_back(parsePragmaDirective(false));
|
||||||
|
|
||||||
@ -164,13 +164,13 @@ ASTPointer<SourceUnit> Parser::parse(CharStream& _charStream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::parsePragmaVersion(SourceLocation const& _location, vector<Token> const& _tokens, vector<string> const& _literals)
|
void Parser::parsePragmaVersion(SourceLocation const& _location, std::vector<Token> const& _tokens, std::vector<std::string> const& _literals)
|
||||||
{
|
{
|
||||||
SemVerMatchExpressionParser parser(_tokens, _literals);
|
SemVerMatchExpressionParser parser(_tokens, _literals);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SemVerMatchExpression matchExpression = parser.parse();
|
SemVerMatchExpression matchExpression = parser.parse();
|
||||||
static SemVerVersion const currentVersion{string(VersionString)};
|
static SemVerVersion const currentVersion{std::string(VersionString)};
|
||||||
// FIXME: only match for major version incompatibility
|
// FIXME: only match for major version incompatibility
|
||||||
if (!matchExpression.matches(currentVersion))
|
if (!matchExpression.matches(currentVersion))
|
||||||
// If m_parserErrorRecovery is true, the same message will appear from SyntaxChecker::visit(),
|
// If m_parserErrorRecovery is true, the same message will appear from SyntaxChecker::visit(),
|
||||||
@ -180,7 +180,7 @@ void Parser::parsePragmaVersion(SourceLocation const& _location, vector<Token> c
|
|||||||
5333_error,
|
5333_error,
|
||||||
_location,
|
_location,
|
||||||
"Source file requires different compiler version (current compiler is " +
|
"Source file requires different compiler version (current compiler is " +
|
||||||
string(VersionString) + ") - note that nightly builds are considered to be "
|
std::string(VersionString) + ") - note that nightly builds are considered to be "
|
||||||
"strictly less than the released version"
|
"strictly less than the released version"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ ASTPointer<StructuredDocumentation> Parser::parseStructuredDocumentation()
|
|||||||
ASTNodeFactory nodeFactory{*this};
|
ASTNodeFactory nodeFactory{*this};
|
||||||
nodeFactory.setLocation(m_scanner->currentCommentLocation());
|
nodeFactory.setLocation(m_scanner->currentCommentLocation());
|
||||||
return nodeFactory.createNode<StructuredDocumentation>(
|
return nodeFactory.createNode<StructuredDocumentation>(
|
||||||
make_shared<ASTString>(m_scanner->currentCommentLiteral())
|
std::make_shared<ASTString>(m_scanner->currentCommentLiteral())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -215,8 +215,8 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective(bool const _finishedPar
|
|||||||
// pragma solidity ^0.4.0 || ^0.3.0;
|
// pragma solidity ^0.4.0 || ^0.3.0;
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::Pragma);
|
expectToken(Token::Pragma);
|
||||||
vector<string> literals;
|
std::vector<std::string> literals;
|
||||||
vector<Token> tokens;
|
std::vector<Token> tokens;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -225,7 +225,7 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective(bool const _finishedPar
|
|||||||
parserError(6281_error, "Token incompatible with Solidity parser as part of pragma directive.");
|
parserError(6281_error, "Token incompatible with Solidity parser as part of pragma directive.");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string literal = m_scanner->currentLiteral();
|
std::string literal = m_scanner->currentLiteral();
|
||||||
if (literal.empty() && TokenTraits::toString(token))
|
if (literal.empty() && TokenTraits::toString(token))
|
||||||
literal = TokenTraits::toString(token);
|
literal = TokenTraits::toString(token);
|
||||||
literals.push_back(literal);
|
literals.push_back(literal);
|
||||||
@ -241,8 +241,8 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective(bool const _finishedPar
|
|||||||
{
|
{
|
||||||
parsePragmaVersion(
|
parsePragmaVersion(
|
||||||
nodeFactory.location(),
|
nodeFactory.location(),
|
||||||
vector<Token>(tokens.begin() + 1, tokens.end()),
|
std::vector<Token>(tokens.begin() + 1, tokens.end()),
|
||||||
vector<string>(literals.begin() + 1, literals.end())
|
std::vector<std::string>(literals.begin() + 1, literals.end())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ ASTPointer<ImportDirective> Parser::parseImportDirective()
|
|||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::Import);
|
expectToken(Token::Import);
|
||||||
ASTPointer<ASTString> path;
|
ASTPointer<ASTString> path;
|
||||||
ASTPointer<ASTString> unitAlias = make_shared<string>();
|
ASTPointer<ASTString> unitAlias = std::make_shared<std::string>();
|
||||||
SourceLocation unitAliasLocation{};
|
SourceLocation unitAliasLocation{};
|
||||||
ImportDirective::SymbolAliasList symbolAliases;
|
ImportDirective::SymbolAliasList symbolAliases;
|
||||||
|
|
||||||
@ -361,8 +361,8 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
|
|||||||
ASTPointer<ASTString> name = nullptr;
|
ASTPointer<ASTString> name = nullptr;
|
||||||
SourceLocation nameLocation{};
|
SourceLocation nameLocation{};
|
||||||
ASTPointer<StructuredDocumentation> documentation;
|
ASTPointer<StructuredDocumentation> documentation;
|
||||||
vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
std::vector<ASTPointer<InheritanceSpecifier>> baseContracts;
|
||||||
vector<ASTPointer<ASTNode>> subNodes;
|
std::vector<ASTPointer<ASTNode>> subNodes;
|
||||||
std::pair<ContractKind, bool> contractKind{};
|
std::pair<ContractKind, bool> contractKind{};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -452,11 +452,11 @@ ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<IdentifierPath> name(parseIdentifierPath());
|
ASTPointer<IdentifierPath> name(parseIdentifierPath());
|
||||||
unique_ptr<vector<ASTPointer<Expression>>> arguments;
|
std::unique_ptr<std::vector<ASTPointer<Expression>>> arguments;
|
||||||
if (m_scanner->currentToken() == Token::LParen)
|
if (m_scanner->currentToken() == Token::LParen)
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
arguments = make_unique<vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
|
arguments = std::make_unique<std::vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RParen);
|
expectToken(Token::RParen);
|
||||||
}
|
}
|
||||||
@ -642,8 +642,8 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction)
|
|||||||
{Token::Receive, "receive function"},
|
{Token::Receive, "receive function"},
|
||||||
}.at(m_scanner->currentToken());
|
}.at(m_scanner->currentToken());
|
||||||
nameLocation = currentLocation();
|
nameLocation = currentLocation();
|
||||||
name = make_shared<ASTString>(TokenTraits::toString(m_scanner->currentToken()));
|
name = std::make_shared<ASTString>(TokenTraits::toString(m_scanner->currentToken()));
|
||||||
string message{
|
std::string message{
|
||||||
"This function is named \"" + *name + "\" but is not the " + expected + " of the contract. "
|
"This function is named \"" + *name + "\" but is not the " + expected + " of the contract. "
|
||||||
"If you intend this to be a " + expected + ", use \"" + *name + "(...) { ... }\" without "
|
"If you intend this to be a " + expected + ", use \"" + *name + "(...) { ... }\" without "
|
||||||
"the \"function\" keyword to define it."
|
"the \"function\" keyword to define it."
|
||||||
@ -661,7 +661,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinition(bool _freeFunction)
|
|||||||
{
|
{
|
||||||
solAssert(kind == Token::Constructor || kind == Token::Fallback || kind == Token::Receive, "");
|
solAssert(kind == Token::Constructor || kind == Token::Fallback || kind == Token::Receive, "");
|
||||||
advance();
|
advance();
|
||||||
name = make_shared<ASTString>();
|
name = std::make_shared<ASTString>();
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionHeaderParserResult header = parseFunctionHeader(false);
|
FunctionHeaderParserResult header = parseFunctionHeader(false);
|
||||||
@ -699,7 +699,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition()
|
|||||||
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
||||||
expectToken(Token::Struct);
|
expectToken(Token::Struct);
|
||||||
auto [name, nameLocation] = expectIdentifierWithLocation();
|
auto [name, nameLocation] = expectIdentifierWithLocation();
|
||||||
vector<ASTPointer<VariableDeclaration>> members;
|
std::vector<ASTPointer<VariableDeclaration>> members;
|
||||||
expectToken(Token::LBrace);
|
expectToken(Token::LBrace);
|
||||||
while (m_scanner->currentToken() != Token::RBrace)
|
while (m_scanner->currentToken() != Token::RBrace)
|
||||||
{
|
{
|
||||||
@ -726,7 +726,7 @@ ASTPointer<EnumDefinition> Parser::parseEnumDefinition()
|
|||||||
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
ASTPointer<StructuredDocumentation> documentation = parseStructuredDocumentation();
|
||||||
expectToken(Token::Enum);
|
expectToken(Token::Enum);
|
||||||
auto [name, nameLocation] = expectIdentifierWithLocation();
|
auto [name, nameLocation] = expectIdentifierWithLocation();
|
||||||
vector<ASTPointer<EnumValue>> members;
|
std::vector<ASTPointer<EnumValue>> members;
|
||||||
expectToken(Token::LBrace);
|
expectToken(Token::LBrace);
|
||||||
|
|
||||||
while (m_scanner->currentToken() != Token::RBrace)
|
while (m_scanner->currentToken() != Token::RBrace)
|
||||||
@ -815,7 +815,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
|||||||
if (mutability != VariableDeclaration::Mutability::Mutable)
|
if (mutability != VariableDeclaration::Mutability::Mutable)
|
||||||
parserError(
|
parserError(
|
||||||
3109_error,
|
3109_error,
|
||||||
string("Mutability already set to ") +
|
std::string("Mutability already set to ") +
|
||||||
(mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
|
(mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
|
||||||
);
|
);
|
||||||
else if (token == Token::Constant)
|
else if (token == Token::Constant)
|
||||||
@ -853,7 +853,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_options.allowEmptyName && m_scanner->currentToken() != Token::Identifier)
|
if (_options.allowEmptyName && m_scanner->currentToken() != Token::Identifier)
|
||||||
identifier = make_shared<ASTString>("");
|
identifier = std::make_shared<ASTString>("");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
@ -940,7 +940,7 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
|
|||||||
return nodeFactory.createNode<ModifierDefinition>(name, nameLocation, documentation, parameters, isVirtual, overrides, block);
|
return nodeFactory.createNode<ModifierDefinition>(name, nameLocation, documentation, parameters, isVirtual, overrides, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<ASTPointer<ASTString>, SourceLocation> Parser::expectIdentifierWithLocation()
|
std::pair<ASTPointer<ASTString>, SourceLocation> Parser::expectIdentifierWithLocation()
|
||||||
{
|
{
|
||||||
SourceLocation nameLocation = currentLocation();
|
SourceLocation nameLocation = currentLocation();
|
||||||
ASTPointer<ASTString> name = expectIdentifierToken();
|
ASTPointer<ASTString> name = expectIdentifierToken();
|
||||||
@ -994,8 +994,8 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
|
|
||||||
expectToken(Token::Using);
|
expectToken(Token::Using);
|
||||||
|
|
||||||
vector<ASTPointer<IdentifierPath>> functions;
|
std::vector<ASTPointer<IdentifierPath>> functions;
|
||||||
vector<optional<Token>> operators;
|
std::vector<std::optional<Token>> operators;
|
||||||
bool const usesBraces = m_scanner->currentToken() == Token::LBrace;
|
bool const usesBraces = m_scanner->currentToken() == Token::LBrace;
|
||||||
if (usesBraces)
|
if (usesBraces)
|
||||||
{
|
{
|
||||||
@ -1009,18 +1009,18 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
Token operator_ = m_scanner->currentToken();
|
Token operator_ = m_scanner->currentToken();
|
||||||
if (!util::contains(userDefinableOperators, operator_))
|
if (!util::contains(userDefinableOperators, operator_))
|
||||||
{
|
{
|
||||||
string operatorName;
|
std::string operatorName;
|
||||||
if (!m_scanner->currentLiteral().empty())
|
if (!m_scanner->currentLiteral().empty())
|
||||||
operatorName = m_scanner->currentLiteral();
|
operatorName = m_scanner->currentLiteral();
|
||||||
else if (char const* tokenString = TokenTraits::toString(operator_))
|
else if (char const* tokenString = TokenTraits::toString(operator_))
|
||||||
operatorName = string(tokenString);
|
operatorName = std::string(tokenString);
|
||||||
|
|
||||||
parserError(
|
parserError(
|
||||||
4403_error,
|
4403_error,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"Not a user-definable operator: {}. Only the following operators can be user-defined: {}",
|
"Not a user-definable operator: {}. Only the following operators can be user-defined: {}",
|
||||||
operatorName,
|
operatorName,
|
||||||
util::joinHumanReadable(userDefinableOperators | ranges::views::transform([](Token _t) { return string{TokenTraits::toString(_t)}; }))
|
util::joinHumanReadable(userDefinableOperators | ranges::views::transform([](Token _t) { return std::string{TokenTraits::toString(_t)}; }))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1028,7 +1028,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
operators.emplace_back(nullopt);
|
operators.emplace_back(std::nullopt);
|
||||||
}
|
}
|
||||||
while (m_scanner->currentToken() == Token::Comma);
|
while (m_scanner->currentToken() == Token::Comma);
|
||||||
expectToken(Token::RBrace);
|
expectToken(Token::RBrace);
|
||||||
@ -1036,7 +1036,7 @@ ASTPointer<UsingForDirective> Parser::parseUsingDirective()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
functions.emplace_back(parseIdentifierPath());
|
functions.emplace_back(parseIdentifierPath());
|
||||||
operators.emplace_back(nullopt);
|
operators.emplace_back(std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<TypeName> typeName;
|
ASTPointer<TypeName> typeName;
|
||||||
@ -1061,11 +1061,11 @@ ASTPointer<ModifierInvocation> Parser::parseModifierInvocation()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
ASTPointer<IdentifierPath> name(parseIdentifierPath());
|
ASTPointer<IdentifierPath> name(parseIdentifierPath());
|
||||||
unique_ptr<vector<ASTPointer<Expression>>> arguments;
|
std::unique_ptr<std::vector<ASTPointer<Expression>>> arguments;
|
||||||
if (m_scanner->currentToken() == Token::LParen)
|
if (m_scanner->currentToken() == Token::LParen)
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
arguments = make_unique<vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
|
arguments = std::make_unique<std::vector<ASTPointer<Expression>>>(parseFunctionCallListArguments());
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
expectToken(Token::RParen);
|
expectToken(Token::RParen);
|
||||||
}
|
}
|
||||||
@ -1122,8 +1122,8 @@ ASTPointer<IdentifierPath> Parser::parseIdentifierPath()
|
|||||||
|
|
||||||
auto [name, nameLocation] = expectIdentifierWithLocation();
|
auto [name, nameLocation] = expectIdentifierWithLocation();
|
||||||
|
|
||||||
vector<ASTString> identifierPath{*name};
|
std::vector<ASTString> identifierPath{*name};
|
||||||
vector<SourceLocation> identifierPathLocations{nameLocation};
|
std::vector<SourceLocation> identifierPathLocations{nameLocation};
|
||||||
|
|
||||||
while (m_scanner->currentToken() == Token::Period)
|
while (m_scanner->currentToken() == Token::Period)
|
||||||
{
|
{
|
||||||
@ -1165,14 +1165,14 @@ ASTPointer<TypeName> Parser::parseTypeName()
|
|||||||
{
|
{
|
||||||
unsigned firstSize;
|
unsigned firstSize;
|
||||||
unsigned secondSize;
|
unsigned secondSize;
|
||||||
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
||||||
ElementaryTypeNameToken elemTypeName(token, firstSize, secondSize);
|
ElementaryTypeNameToken elemTypeName(token, firstSize, secondSize);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
advance();
|
advance();
|
||||||
auto stateMutability = elemTypeName.token() == Token::Address
|
auto stateMutability = elemTypeName.token() == Token::Address
|
||||||
? optional<StateMutability>{StateMutability::NonPayable}
|
? std::optional<StateMutability>{StateMutability::NonPayable}
|
||||||
: nullopt;
|
: std::nullopt;
|
||||||
if (TokenTraits::isStateMutabilitySpecifier(m_scanner->currentToken()))
|
if (TokenTraits::isStateMutabilitySpecifier(m_scanner->currentToken()))
|
||||||
{
|
{
|
||||||
if (elemTypeName.token() == Token::Address)
|
if (elemTypeName.token() == Token::Address)
|
||||||
@ -1228,7 +1228,7 @@ ASTPointer<Mapping> Parser::parseMapping()
|
|||||||
Token token = m_scanner->currentToken();
|
Token token = m_scanner->currentToken();
|
||||||
unsigned firstSize;
|
unsigned firstSize;
|
||||||
unsigned secondSize;
|
unsigned secondSize;
|
||||||
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
||||||
if (token == Token::Identifier)
|
if (token == Token::Identifier)
|
||||||
keyType = parseUserDefinedTypeName();
|
keyType = parseUserDefinedTypeName();
|
||||||
else if (TokenTraits::isElementaryTypeName(token))
|
else if (TokenTraits::isElementaryTypeName(token))
|
||||||
@ -1240,13 +1240,13 @@ ASTPointer<Mapping> Parser::parseMapping()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type");
|
fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type");
|
||||||
ASTPointer<ASTString> keyName = make_shared<ASTString>("");
|
ASTPointer<ASTString> keyName = std::make_shared<ASTString>("");
|
||||||
SourceLocation keyNameLocation{};
|
SourceLocation keyNameLocation{};
|
||||||
if (m_scanner->currentToken() == Token::Identifier)
|
if (m_scanner->currentToken() == Token::Identifier)
|
||||||
tie(keyName, keyNameLocation) = expectIdentifierWithLocation();
|
tie(keyName, keyNameLocation) = expectIdentifierWithLocation();
|
||||||
expectToken(Token::DoubleArrow);
|
expectToken(Token::DoubleArrow);
|
||||||
ASTPointer<TypeName> valueType = parseTypeName();
|
ASTPointer<TypeName> valueType = parseTypeName();
|
||||||
ASTPointer<ASTString> valueName = make_shared<ASTString>("");
|
ASTPointer<ASTString> valueName = std::make_shared<ASTString>("");
|
||||||
SourceLocation valueNameLocation{};
|
SourceLocation valueNameLocation{};
|
||||||
if (m_scanner->currentToken() == Token::Identifier)
|
if (m_scanner->currentToken() == Token::Identifier)
|
||||||
tie(valueName, valueNameLocation) = expectIdentifierWithLocation();
|
tie(valueName, valueNameLocation) = expectIdentifierWithLocation();
|
||||||
@ -1262,7 +1262,7 @@ ASTPointer<ParameterList> Parser::parseParameterList(
|
|||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
vector<ASTPointer<VariableDeclaration>> parameters;
|
std::vector<ASTPointer<VariableDeclaration>> parameters;
|
||||||
VarDeclParserOptions options(_options);
|
VarDeclParserOptions options(_options);
|
||||||
options.allowEmptyName = true;
|
options.allowEmptyName = true;
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
@ -1294,7 +1294,7 @@ ASTPointer<Block> Parser::parseBlock(bool _allowUnchecked, ASTPointer<ASTString>
|
|||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
expectToken(Token::LBrace);
|
expectToken(Token::LBrace);
|
||||||
vector<ASTPointer<Statement>> statements;
|
std::vector<ASTPointer<Statement>> statements;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (m_scanner->currentToken() != Token::RBrace)
|
while (m_scanner->currentToken() != Token::RBrace)
|
||||||
@ -1326,7 +1326,7 @@ ASTPointer<Statement> Parser::parseStatement(bool _allowUnchecked)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (m_scanner->currentCommentLiteral() != "")
|
if (m_scanner->currentCommentLiteral() != "")
|
||||||
docString = make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
docString = std::make_shared<ASTString>(m_scanner->currentCommentLiteral());
|
||||||
switch (m_scanner->currentToken())
|
switch (m_scanner->currentToken())
|
||||||
{
|
{
|
||||||
case Token::If:
|
case Token::If:
|
||||||
@ -1421,15 +1421,15 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
|||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<vector<ASTPointer<ASTString>>> flags;
|
ASTPointer<std::vector<ASTPointer<ASTString>>> flags;
|
||||||
if (m_scanner->currentToken() == Token::LParen)
|
if (m_scanner->currentToken() == Token::LParen)
|
||||||
{
|
{
|
||||||
flags = make_shared<vector<ASTPointer<ASTString>>>();
|
flags = std::make_shared<std::vector<ASTPointer<ASTString>>>();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
advance();
|
advance();
|
||||||
expectToken(Token::StringLiteral, false);
|
expectToken(Token::StringLiteral, false);
|
||||||
flags->emplace_back(make_shared<ASTString>(m_scanner->currentLiteral()));
|
flags->emplace_back(std::make_shared<ASTString>(m_scanner->currentLiteral()));
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
while (m_scanner->currentToken() == Token::Comma);
|
while (m_scanner->currentToken() == Token::Comma);
|
||||||
@ -1437,12 +1437,12 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
|
|||||||
}
|
}
|
||||||
|
|
||||||
yul::Parser asmParser(m_errorReporter, dialect);
|
yul::Parser asmParser(m_errorReporter, dialect);
|
||||||
shared_ptr<yul::Block> block = asmParser.parseInline(m_scanner);
|
std::shared_ptr<yul::Block> block = asmParser.parseInline(m_scanner);
|
||||||
if (block == nullptr)
|
if (block == nullptr)
|
||||||
BOOST_THROW_EXCEPTION(FatalError());
|
BOOST_THROW_EXCEPTION(FatalError());
|
||||||
|
|
||||||
location.end = nativeLocationOf(*block).end;
|
location.end = nativeLocationOf(*block).end;
|
||||||
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, std::move(flags), block);
|
return std::make_shared<InlineAssembly>(nextID(), location, _docString, dialect, std::move(flags), block);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
|
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)
|
||||||
@ -1472,7 +1472,7 @@ ASTPointer<TryStatement> Parser::parseTryStatement(ASTPointer<ASTString> const&
|
|||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::Try);
|
expectToken(Token::Try);
|
||||||
ASTPointer<Expression> externalCall = parseExpression();
|
ASTPointer<Expression> externalCall = parseExpression();
|
||||||
vector<ASTPointer<TryCatchClause>> clauses;
|
std::vector<ASTPointer<TryCatchClause>> clauses;
|
||||||
|
|
||||||
ASTNodeFactory successClauseFactory(*this);
|
ASTNodeFactory successClauseFactory(*this);
|
||||||
ASTPointer<ParameterList> returnsParameters;
|
ASTPointer<ParameterList> returnsParameters;
|
||||||
@ -1487,7 +1487,7 @@ ASTPointer<TryStatement> Parser::parseTryStatement(ASTPointer<ASTString> const&
|
|||||||
ASTPointer<Block> successBlock = parseBlock();
|
ASTPointer<Block> successBlock = parseBlock();
|
||||||
successClauseFactory.setEndPositionFromNode(successBlock);
|
successClauseFactory.setEndPositionFromNode(successBlock);
|
||||||
clauses.emplace_back(successClauseFactory.createNode<TryCatchClause>(
|
clauses.emplace_back(successClauseFactory.createNode<TryCatchClause>(
|
||||||
make_shared<ASTString>(), returnsParameters, successBlock
|
std::make_shared<ASTString>(), returnsParameters, successBlock
|
||||||
));
|
));
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -1506,7 +1506,7 @@ ASTPointer<TryCatchClause> Parser::parseCatchClause()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::Catch);
|
expectToken(Token::Catch);
|
||||||
ASTPointer<ASTString> errorName = make_shared<string>();
|
ASTPointer<ASTString> errorName = std::make_shared<std::string>();
|
||||||
ASTPointer<ParameterList> errorParameters;
|
ASTPointer<ParameterList> errorParameters;
|
||||||
if (m_scanner->currentToken() != Token::LBrace)
|
if (m_scanner->currentToken() != Token::LBrace)
|
||||||
{
|
{
|
||||||
@ -1674,17 +1674,17 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now see whether we have a variable declaration or an expression.
|
// Now see whether we have a variable declaration or an expression.
|
||||||
tie(statementType, iap) = tryParseIndexAccessedPath();
|
std::tie(statementType, iap) = tryParseIndexAccessedPath();
|
||||||
switch (statementType)
|
switch (statementType)
|
||||||
{
|
{
|
||||||
case LookAheadInfo::VariableDeclaration:
|
case LookAheadInfo::VariableDeclaration:
|
||||||
{
|
{
|
||||||
vector<ASTPointer<VariableDeclaration>> variables;
|
std::vector<ASTPointer<VariableDeclaration>> variables;
|
||||||
ASTPointer<Expression> value;
|
ASTPointer<Expression> value;
|
||||||
// We have already parsed something like `(,,,,a.b.c[2][3]`
|
// We have already parsed something like `(,,,,a.b.c[2][3]`
|
||||||
VarDeclParserOptions options;
|
VarDeclParserOptions options;
|
||||||
options.allowLocationSpecifier = true;
|
options.allowLocationSpecifier = true;
|
||||||
variables = vector<ASTPointer<VariableDeclaration>>(emptyComponents, nullptr);
|
variables = std::vector<ASTPointer<VariableDeclaration>>(emptyComponents, nullptr);
|
||||||
variables.push_back(parseVariableDeclaration(options, typeNameFromIndexAccessStructure(iap)));
|
variables.push_back(parseVariableDeclaration(options, typeNameFromIndexAccessStructure(iap)));
|
||||||
|
|
||||||
while (m_scanner->currentToken() != Token::RParen)
|
while (m_scanner->currentToken() != Token::RParen)
|
||||||
@ -1704,7 +1704,7 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
|
|||||||
case LookAheadInfo::Expression:
|
case LookAheadInfo::Expression:
|
||||||
{
|
{
|
||||||
// Complete parsing the expression in the current component.
|
// Complete parsing the expression in the current component.
|
||||||
vector<ASTPointer<Expression>> components(emptyComponents, nullptr);
|
std::vector<ASTPointer<Expression>> components(emptyComponents, nullptr);
|
||||||
components.push_back(parseExpression(expressionFromIndexAccessStructure(iap)));
|
components.push_back(parseExpression(expressionFromIndexAccessStructure(iap)));
|
||||||
while (m_scanner->currentToken() != Token::RParen)
|
while (m_scanner->currentToken() != Token::RParen)
|
||||||
{
|
{
|
||||||
@ -1724,7 +1724,7 @@ ASTPointer<Statement> Parser::parseSimpleStatement(ASTPointer<ASTString> const&
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tie(statementType, iap) = tryParseIndexAccessedPath();
|
std::tie(statementType, iap) = tryParseIndexAccessedPath();
|
||||||
switch (statementType)
|
switch (statementType)
|
||||||
{
|
{
|
||||||
case LookAheadInfo::VariableDeclaration:
|
case LookAheadInfo::VariableDeclaration:
|
||||||
@ -1749,7 +1749,7 @@ bool Parser::IndexAccessedPath::empty() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAccessedPath()
|
std::pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAccessedPath()
|
||||||
{
|
{
|
||||||
// These two cases are very hard to distinguish:
|
// These two cases are very hard to distinguish:
|
||||||
// x[7 * 20 + 3] a; and x[7 * 20 + 3] = 9;
|
// x[7 * 20 + 3] a; and x[7 * 20 + 3] = 9;
|
||||||
@ -1763,7 +1763,7 @@ pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAcce
|
|||||||
{
|
{
|
||||||
case LookAheadInfo::VariableDeclaration:
|
case LookAheadInfo::VariableDeclaration:
|
||||||
case LookAheadInfo::Expression:
|
case LookAheadInfo::Expression:
|
||||||
return make_pair(statementType, IndexAccessedPath());
|
return std::make_pair(statementType, IndexAccessedPath());
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1775,9 +1775,9 @@ pair<Parser::LookAheadInfo, Parser::IndexAccessedPath> Parser::tryParseIndexAcce
|
|||||||
IndexAccessedPath iap = parseIndexAccessedPath();
|
IndexAccessedPath iap = parseIndexAccessedPath();
|
||||||
|
|
||||||
if (m_scanner->currentToken() == Token::Identifier || TokenTraits::isLocationSpecifier(m_scanner->currentToken()))
|
if (m_scanner->currentToken() == Token::Identifier || TokenTraits::isLocationSpecifier(m_scanner->currentToken()))
|
||||||
return make_pair(LookAheadInfo::VariableDeclaration, std::move(iap));
|
return std::make_pair(LookAheadInfo::VariableDeclaration, std::move(iap));
|
||||||
else
|
else
|
||||||
return make_pair(LookAheadInfo::Expression, std::move(iap));
|
return std::make_pair(LookAheadInfo::Expression, std::move(iap));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
|
ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStatement(
|
||||||
@ -1795,7 +1795,7 @@ ASTPointer<VariableDeclarationStatement> Parser::parseVariableDeclarationStateme
|
|||||||
|
|
||||||
VarDeclParserOptions options;
|
VarDeclParserOptions options;
|
||||||
options.allowLocationSpecifier = true;
|
options.allowLocationSpecifier = true;
|
||||||
vector<ASTPointer<VariableDeclaration>> variables;
|
std::vector<ASTPointer<VariableDeclaration>> variables;
|
||||||
variables.emplace_back(parseVariableDeclaration(options, _lookAheadArrayType));
|
variables.emplace_back(parseVariableDeclaration(options, _lookAheadArrayType));
|
||||||
nodeFactory.setEndPositionFromNode(variables.back());
|
nodeFactory.setEndPositionFromNode(variables.back());
|
||||||
|
|
||||||
@ -2021,7 +2021,7 @@ ASTPointer<Expression> Parser::parseLiteral()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
Token initialToken = m_scanner->currentToken();
|
Token initialToken = m_scanner->currentToken();
|
||||||
ASTPointer<ASTString> value = make_shared<string>(m_scanner->currentLiteral());
|
ASTPointer<ASTString> value = std::make_shared<std::string>(m_scanner->currentLiteral());
|
||||||
|
|
||||||
switch (initialToken)
|
switch (initialToken)
|
||||||
{
|
{
|
||||||
@ -2091,7 +2091,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
|
|||||||
// Inside expressions "type" is the name of a special, globally-available function.
|
// Inside expressions "type" is the name of a special, globally-available function.
|
||||||
nodeFactory.markEndPosition();
|
nodeFactory.markEndPosition();
|
||||||
advance();
|
advance();
|
||||||
expression = nodeFactory.createNode<Identifier>(make_shared<ASTString>("type"));
|
expression = nodeFactory.createNode<Identifier>(std::make_shared<ASTString>("type"));
|
||||||
break;
|
break;
|
||||||
case Token::LParen:
|
case Token::LParen:
|
||||||
case Token::LBrack:
|
case Token::LBrack:
|
||||||
@ -2100,7 +2100,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
|
|||||||
// Special cases: ()/[] is empty tuple/array type, (x) is not a real tuple,
|
// Special cases: ()/[] is empty tuple/array type, (x) is not a real tuple,
|
||||||
// (x,) is one-dimensional tuple, elements in arrays cannot be left out, only in tuples.
|
// (x,) is one-dimensional tuple, elements in arrays cannot be left out, only in tuples.
|
||||||
advance();
|
advance();
|
||||||
vector<ASTPointer<Expression>> components;
|
std::vector<ASTPointer<Expression>> components;
|
||||||
Token oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack);
|
Token oppositeToken = (token == Token::LParen ? Token::RParen : Token::RBrack);
|
||||||
bool isArray = (token == Token::LBrack);
|
bool isArray = (token == Token::LBrack);
|
||||||
|
|
||||||
@ -2133,7 +2133,7 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
|
|||||||
//used for casts
|
//used for casts
|
||||||
unsigned firstSize;
|
unsigned firstSize;
|
||||||
unsigned secondSize;
|
unsigned secondSize;
|
||||||
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
std::tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
||||||
auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
|
auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
|
||||||
ElementaryTypeNameToken(m_scanner->currentToken(), firstSize, secondSize)
|
ElementaryTypeNameToken(m_scanner->currentToken(), firstSize, secondSize)
|
||||||
);
|
);
|
||||||
@ -2147,10 +2147,10 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
|
|||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
|
std::vector<ASTPointer<Expression>> Parser::parseFunctionCallListArguments()
|
||||||
{
|
{
|
||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
vector<ASTPointer<Expression>> arguments;
|
std::vector<ASTPointer<Expression>> arguments;
|
||||||
if (m_scanner->currentToken() != Token::RParen)
|
if (m_scanner->currentToken() != Token::RParen)
|
||||||
{
|
{
|
||||||
arguments.push_back(parseExpression());
|
arguments.push_back(parseExpression());
|
||||||
@ -2226,17 +2226,17 @@ bool Parser::variableDeclarationStart()
|
|||||||
(currentToken == Token::Function && m_scanner->peekNextToken() == Token::LParen);
|
(currentToken == Token::Function && m_scanner->peekNextToken() == Token::LParen);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes)
|
std::optional<std::string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> const& _nodes)
|
||||||
{
|
{
|
||||||
// We circumvent the scanner here, because it skips non-docstring comments.
|
// We circumvent the scanner here, because it skips non-docstring comments.
|
||||||
static regex const licenseNameRegex("([a-zA-Z0-9 ()+.-]+)");
|
static std::regex const licenseNameRegex("([a-zA-Z0-9 ()+.-]+)");
|
||||||
static regex const licenseDeclarationRegex("SPDX-License-Identifier:\\s*(.+?)([\n\r]|(\\*/))");
|
static std::regex const licenseDeclarationRegex("SPDX-License-Identifier:\\s*(.+?)([\n\r]|(\\*/))");
|
||||||
|
|
||||||
// Search inside all parts of the source not covered by parsed nodes.
|
// Search inside all parts of the source not covered by parsed nodes.
|
||||||
// This will leave e.g. "global comments".
|
// This will leave e.g. "global comments".
|
||||||
using iter = std::string::const_iterator;
|
using iter = std::string::const_iterator;
|
||||||
vector<pair<iter, iter>> sequencesToSearch;
|
std::vector<std::pair<iter, iter>> sequencesToSearch;
|
||||||
string const& source = m_scanner->charStream().source();
|
std::string const& source = m_scanner->charStream().source();
|
||||||
sequencesToSearch.emplace_back(source.begin(), source.end());
|
sequencesToSearch.emplace_back(source.begin(), source.end());
|
||||||
for (ASTPointer<ASTNode> const& node: _nodes)
|
for (ASTPointer<ASTNode> const& node: _nodes)
|
||||||
if (node->location().hasText())
|
if (node->location().hasText())
|
||||||
@ -2245,7 +2245,7 @@ optional<string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> cons
|
|||||||
sequencesToSearch.emplace_back(source.begin() + node->location().end, source.end());
|
sequencesToSearch.emplace_back(source.begin() + node->location().end, source.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> licenseNames;
|
std::vector<std::string> licenseNames;
|
||||||
for (auto const& [start, end]: sequencesToSearch)
|
for (auto const& [start, end]: sequencesToSearch)
|
||||||
{
|
{
|
||||||
auto declarationsBegin = std::sregex_iterator(start, end, licenseDeclarationRegex);
|
auto declarationsBegin = std::sregex_iterator(start, end, licenseDeclarationRegex);
|
||||||
@ -2254,14 +2254,14 @@ optional<string> Parser::findLicenseString(std::vector<ASTPointer<ASTNode>> cons
|
|||||||
for (std::sregex_iterator declIt = declarationsBegin; declIt != declarationsEnd; ++declIt)
|
for (std::sregex_iterator declIt = declarationsBegin; declIt != declarationsEnd; ++declIt)
|
||||||
if (!declIt->empty())
|
if (!declIt->empty())
|
||||||
{
|
{
|
||||||
string license = boost::trim_copy(string((*declIt)[1]));
|
std::string license = boost::trim_copy(std::string((*declIt)[1]));
|
||||||
licenseNames.emplace_back(std::move(license));
|
licenseNames.emplace_back(std::move(license));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (licenseNames.size() == 1)
|
if (licenseNames.size() == 1)
|
||||||
{
|
{
|
||||||
string const& license = licenseNames.front();
|
std::string const& license = licenseNames.front();
|
||||||
if (regex_match(license, licenseNameRegex))
|
if (regex_match(license, licenseNameRegex))
|
||||||
return license;
|
return license;
|
||||||
else
|
else
|
||||||
@ -2340,7 +2340,7 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
|
|||||||
{
|
{
|
||||||
unsigned firstNum;
|
unsigned firstNum;
|
||||||
unsigned secondNum;
|
unsigned secondNum;
|
||||||
tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
|
std::tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
|
||||||
auto expressionType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
|
auto expressionType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
|
||||||
ElementaryTypeNameToken(m_scanner->currentToken(), firstNum, secondNum)
|
ElementaryTypeNameToken(m_scanner->currentToken(), firstNum, secondNum)
|
||||||
);
|
);
|
||||||
@ -2394,8 +2394,8 @@ ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAcces
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vector<ASTString> path;
|
std::vector<ASTString> path;
|
||||||
vector<SourceLocation> pathLocations;
|
std::vector<SourceLocation> pathLocations;
|
||||||
|
|
||||||
for (auto const& el: _iap.path)
|
for (auto const& el: _iap.path)
|
||||||
{
|
{
|
||||||
@ -2434,7 +2434,7 @@ ASTPointer<Expression> Parser::expressionFromIndexAccessStructure(
|
|||||||
Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
|
Identifier const& identifier = dynamic_cast<Identifier const&>(*_iap.path[i]);
|
||||||
expression = nodeFactory.createNode<MemberAccess>(
|
expression = nodeFactory.createNode<MemberAccess>(
|
||||||
expression,
|
expression,
|
||||||
make_shared<ASTString>(identifier.name()),
|
std::make_shared<ASTString>(identifier.name()),
|
||||||
identifier.location()
|
identifier.location()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2454,7 +2454,7 @@ ASTPointer<ParameterList> Parser::createEmptyParameterList()
|
|||||||
RecursionGuard recursionGuard(*this);
|
RecursionGuard recursionGuard(*this);
|
||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
nodeFactory.setLocationEmpty();
|
nodeFactory.setLocationEmpty();
|
||||||
return nodeFactory.createNode<ParameterList>(vector<ASTPointer<VariableDeclaration>>());
|
return nodeFactory.createNode<ParameterList>(std::vector<ASTPointer<VariableDeclaration>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTPointer<ASTString> Parser::expectIdentifierToken()
|
ASTPointer<ASTString> Parser::expectIdentifierToken()
|
||||||
@ -2468,7 +2468,7 @@ ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddress()
|
|||||||
ASTPointer<ASTString> result;
|
ASTPointer<ASTString> result;
|
||||||
if (m_scanner->currentToken() == Token::Address)
|
if (m_scanner->currentToken() == Token::Address)
|
||||||
{
|
{
|
||||||
result = make_shared<ASTString>("address");
|
result = std::make_shared<ASTString>("address");
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2481,7 +2481,7 @@ ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddress()
|
|||||||
|
|
||||||
ASTPointer<ASTString> Parser::getLiteralAndAdvance()
|
ASTPointer<ASTString> Parser::getLiteralAndAdvance()
|
||||||
{
|
{
|
||||||
ASTPointer<ASTString> identifier = make_shared<ASTString>(m_scanner->currentLiteral());
|
ASTPointer<ASTString> identifier = std::make_shared<ASTString>(m_scanner->currentLiteral());
|
||||||
advance();
|
advance();
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
@ -2504,7 +2504,7 @@ ASTPointer<ASTString> Parser::getStdlibImportPathAndAdvance()
|
|||||||
if (m_scanner->currentToken() == Token::Period)
|
if (m_scanner->currentToken() == Token::Period)
|
||||||
advance();
|
advance();
|
||||||
ASTPointer<ASTString> library = expectIdentifierToken();
|
ASTPointer<ASTString> library = expectIdentifierToken();
|
||||||
return make_shared<ASTString>(*std + "." + *library);
|
return std::make_shared<ASTString>(*std + "." + *library);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ NAMESPACE_STD_FREE_FILES=(
|
|||||||
libsolidity/codegen/*
|
libsolidity/codegen/*
|
||||||
libsolidity/formal/*
|
libsolidity/formal/*
|
||||||
libsolidity/interface/*
|
libsolidity/interface/*
|
||||||
|
libsolidity/lsp/*
|
||||||
|
libsolidity/parsing/*
|
||||||
)
|
)
|
||||||
|
|
||||||
(
|
(
|
||||||
|
Loading…
Reference in New Issue
Block a user