From fc224f74c7fbff547714a59470fab0d2b1410168 Mon Sep 17 00:00:00 2001 From: Marenz Date: Thu, 28 Oct 2021 15:30:31 +0200 Subject: [PATCH] Evaluate absolute paths for imports in 'parsing' stage --- Changelog.md | 1 + libsolidity/interface/CompilerStack.cpp | 26 ++++--- libsolidity/interface/CompilerStack.h | 4 +- .../args | 1 + .../input.json | 12 ++++ .../output.json | 67 +++++++++++++++++++ .../not_existing_import_parseOnly.json | 1 + 7 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 test/cmdlineTests/standard_parsing_import_absolute_paths/args create mode 100644 test/cmdlineTests/standard_parsing_import_absolute_paths/input.json create mode 100644 test/cmdlineTests/standard_parsing_import_absolute_paths/output.json diff --git a/Changelog.md b/Changelog.md index ff183e22b..aad7b2a53 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Compiler Features: * Commandline Interface: Accept nested brackets in step sequences passed to ``--yul-optimizations``. * Commandline Interface: Add ``--debug-info`` option for selecting how much extra debug information should be included in the produced EVM assembly and Yul code. * Commandline Interface: Use different colors when printing errors, warnings and infos. + * JSON AST: Set absolute paths of imports earlier, in the ``parsing`` stage. * SMTChecker: Output values for ``block.*``, ``msg.*`` and ``tx.*`` variables that are present in the called functions. * SMTChecker: Report contract invariants and reentrancy properties. This can be enabled via the CLI option ``--model-checker-invariants`` or the Standard JSON option ``settings.modelChecker.invariants``. * Standard JSON: Accept nested brackets in step sequences passed to ``settings.optimizer.details.yulDetails.optimizerSteps``. diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 9fa3cb164..27e0f9d3a 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -350,8 +350,22 @@ bool CompilerStack::parse() else { source.ast->annotation().path = path; + + for (auto const& import: ASTNode::filteredNodes(source.ast->nodes())) + { + solAssert(!import->path().empty(), "Import path cannot be empty."); + + // The current value of `path` is the absolute path as seen from this source file. + // We first have to apply remappings before we can store the actual absolute path + // as seen globally. + import->annotation().absolutePath = applyRemapping(util::absolutePath( + import->path(), + path + ), path); + } + if (m_stopAfter >= ParsedAndImported) - for (auto const& newSource: loadMissingSources(*source.ast, path)) + for (auto const& newSource: loadMissingSources(*source.ast)) { string const& newPath = newSource.first; string const& newContents = newSource.second; @@ -1091,7 +1105,7 @@ string const& CompilerStack::Source::ipfsUrl() const return ipfsUrlCached; } -StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string const& _sourcePath) +StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast) { solAssert(m_stackState < ParsedAndImported, ""); StringMap newSources; @@ -1100,14 +1114,8 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string for (auto const& node: _ast.nodes()) if (ImportDirective const* import = dynamic_cast(node.get())) { - solAssert(!import->path().empty(), "Import path cannot be empty."); + string const& importPath = *import->annotation().absolutePath; - string importPath = util::absolutePath(import->path(), _sourcePath); - // The current value of `path` is the absolute path as seen from this source file. - // We first have to apply remappings before we can store the actual absolute path - // as seen globally. - importPath = applyRemapping(importPath, _sourcePath); - import->annotation().absolutePath = importPath; if (m_sources.count(importPath) || newSources.count(importPath)) continue; diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index c97581a65..3609662e0 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -392,9 +392,9 @@ private: void findAndReportCyclicContractDependencies(); /// Loads the missing sources from @a _ast (named @a _path) using the callback - /// @a m_readFile and stores the absolute paths of all imports in the AST annotations. + /// @a m_readFile /// @returns the newly loaded sources. - StringMap loadMissingSources(SourceUnit const& _ast, std::string const& _path); + StringMap loadMissingSources(SourceUnit const& _ast); std::string applyRemapping(std::string const& _path, std::string const& _context); void resolveImports(); diff --git a/test/cmdlineTests/standard_parsing_import_absolute_paths/args b/test/cmdlineTests/standard_parsing_import_absolute_paths/args new file mode 100644 index 000000000..a905f1fe6 --- /dev/null +++ b/test/cmdlineTests/standard_parsing_import_absolute_paths/args @@ -0,0 +1 @@ +--pretty-json --json-indent 4 diff --git a/test/cmdlineTests/standard_parsing_import_absolute_paths/input.json b/test/cmdlineTests/standard_parsing_import_absolute_paths/input.json new file mode 100644 index 000000000..9ec5150b4 --- /dev/null +++ b/test/cmdlineTests/standard_parsing_import_absolute_paths/input.json @@ -0,0 +1,12 @@ +{ + "language": "Solidity", + "sources": { + "/project/../C.sol": {"content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\nimport \"../L.sol\";"}, + "/lib/L.sol": {"content": "//SPDX-License-Identifier: GPL-2.0\npragma solidity >=0.0;\n"} + }, + "settings": { + "stopAfter": "parsing", + "remappings": [":/project/=/lib/"], + "outputSelection": {"*": {"": ["ast"]}} + } +} diff --git a/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json b/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json new file mode 100644 index 000000000..1982561ef --- /dev/null +++ b/test/cmdlineTests/standard_parsing_import_absolute_paths/output.json @@ -0,0 +1,67 @@ +{ + "sources": + { + "/lib/L.sol": + { + "ast": + { + "absolutePath": "/lib/L.sol", + "id": 2, + "license": "GPL-2.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 1, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "35:22:0" + } + ], + "src": "35:23:0" + }, + "id": 0 + }, + "/project/../C.sol": + { + "ast": + { + "absolutePath": "/project/../C.sol", + "id": 5, + "license": "GPL-2.0", + "nodeType": "SourceUnit", + "nodes": + [ + { + "id": 3, + "literals": + [ + "solidity", + ">=", + "0.0" + ], + "nodeType": "PragmaDirective", + "src": "35:22:1" + }, + { + "absolutePath": "/lib/L.sol", + "file": "../L.sol", + "id": 4, + "nameLocation": "-1:-1:-1", + "nodeType": "ImportDirective", + "src": "58:18:1", + "symbolAliases": [], + "unitAlias": "" + } + ], + "src": "35:41:1" + }, + "id": 1 + } + } +} diff --git a/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json b/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json index a42a10aed..a36c59fff 100644 --- a/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json +++ b/test/libsolidity/ASTJSON/not_existing_import_parseOnly.json @@ -5,6 +5,7 @@ "nodes": [ { + "absolutePath": "notexisting.sol", "file": "notexisting.sol", "id": 1, "nameLocation": "28:11:1",