diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 65831ec868e4..4be323943237 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -520,7 +520,7 @@ void DeclarationRegistrationHelper::endVisit(SourceUnit& _sourceUnit) bool DeclarationRegistrationHelper::visit(ImportDirective& _import) { SourceUnit const* importee = _import.annotation().sourceUnit; - solAssert(!!importee, ""); +// solAssert(!!importee, ""); Not sure about this Assert, Source unit will be null when not processing the imports if (!m_scopes[importee]) m_scopes[importee] = make_shared(nullptr, m_scopes[nullptr].get()); m_scopes[&_import] = m_scopes[importee]; diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 78f1dba7462a..3b91f2b9c6c4 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -247,7 +247,7 @@ bool ASTJsonConverter::visit(ImportDirective const& _node) std::vector> attributes = { make_pair("file", _node.path()), make_pair("absolutePath", _node.annotation().absolutePath), - make_pair(m_legacy ? "SourceUnit" : "sourceUnit", nodeId(*_node.annotation().sourceUnit)), + make_pair(m_legacy ? "SourceUnit" : "sourceUnit", idOrNull(_node.annotation().sourceUnit)), make_pair("scope", idOrNull(_node.scope())) }; attributes.emplace_back("unitAlias", _node.name()); @@ -363,7 +363,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node) make_pair("implemented", _node.isImplemented()), make_pair("scope", idOrNull(_node.scope())) }; - if (_node.isPartOfExternalInterface()) + if (_node.scope() && _node.isPartOfExternalInterface()) attributes.emplace_back("functionSelector", _node.externalIdentifierHex()); if (!_node.annotation().baseFunctions.empty()) attributes.emplace_back(make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true))); @@ -388,7 +388,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node) make_pair("scope", idOrNull(_node.scope())), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }; - if (_node.isStateVariable() && _node.isPublic()) + if (_node.scope() && _node.isStateVariable() && _node.isPublic()) attributes.emplace_back("functionSelector", _node.externalIdentifierHex()); if (m_inEvent) attributes.emplace_back("indexed", _node.isIndexed()); @@ -896,6 +896,7 @@ string ASTJsonConverter::functionCallKind(FunctionCallKind _kind) case FunctionCallKind::StructConstructorCall: return "structConstructorCall"; default: + return "unset"; solAssert(false, "Unknown kind of function call."); } } diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 17348c24278f..d2dabf5cada5 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -221,6 +221,10 @@ void CompilerStack::reset(bool _keepSettings) TypeProvider::reset(); } +void CompilerStack::setOnlyParsing(bool _onlyParsing) { + m_onlyParsing = _onlyParsing; +} + void CompilerStack::setSources(StringMap _sources) { if (m_stackState == SourcesSet) @@ -259,10 +263,12 @@ bool CompilerStack::parse() source.ast->annotation().path = path; for (auto const& newSource: loadMissingSources(*source.ast, path)) { - string const& newPath = newSource.first; - string const& newContents = newSource.second; - m_sources[newPath].scanner = make_shared(CharStream(newContents, newPath)); - sourcesToParse.push_back(newPath); + if(!m_onlyParsing) { + string const& newPath = newSource.first; + string const& newContents = newSource.second; + m_sources[newPath].scanner = make_shared(CharStream(newContents, newPath)); + sourcesToParse.push_back(newPath); + } } } } @@ -465,6 +471,9 @@ bool CompilerStack::analyze() bool CompilerStack::parseAndAnalyze() { bool success = parse(); + if(m_onlyParsing) + return success; + if (success || m_parserErrorRecovery) success = analyze(); return success; @@ -534,8 +543,8 @@ void CompilerStack::link() vector CompilerStack::contractNames() const { - if (m_stackState < AnalysisPerformed) - BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); +// if (m_stackState < AnalysisPerformed) +// BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Parsing was not successful.")); vector contractNames; for (auto const& contract: m_contracts) contractNames.push_back(contract.first); @@ -937,7 +946,7 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string // as seen globally. importPath = applyRemapping(importPath, _sourcePath); import->annotation().absolutePath = importPath; - if (m_sources.count(importPath) || newSources.count(importPath)) + if (m_sources.count(importPath) || newSources.count(importPath) || m_onlyParsing) continue; ReadCallback::Result result{false, string("File not supplied initially.")}; @@ -1023,6 +1032,9 @@ void CompilerStack::resolveImports() if (ImportDirective const* import = dynamic_cast(node.get())) { string const& path = import->annotation().absolutePath; + if(!m_sources.count(path)) { + continue; + } solAssert(m_sources.count(path), ""); import->annotation().sourceUnit = m_sources[path].ast.get(); toposort(&m_sources[path]); diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 8bc8828c6305..1ce5c78ca374 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -188,6 +188,9 @@ class CompilerStack: boost::noncopyable /// @param _metadataHash can be IPFS, Bzzr1, None void setMetadataHash(MetadataHash _metadataHash); + /// Sets the compiler in only parsing mode. No imports will be processed, compilation will be skipped. + void setOnlyParsing(bool _onlyParsing); + /// Sets the sources. Must be set before parsing. void setSources(StringMap _sources); @@ -461,6 +464,7 @@ class CompilerStack: boost::noncopyable /// If this is true, the stack will refuse to generate code. bool m_hasError = false; bool m_release = VersionIsRelease; + bool m_onlyParsing = false; }; } diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 90c2931c56ab..ef17876b9724 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -109,6 +109,7 @@ static string const g_strAsmJson = "asm-json"; static string const g_strAssemble = "assemble"; static string const g_strAst = "ast"; static string const g_strAstJson = "ast-json"; +static string const g_strAstJsonNoCompile = "ast-json-no-compile"; static string const g_strAstCompactJson = "ast-compact-json"; static string const g_strBinary = "bin"; static string const g_strBinaryRuntime = "bin-runtime"; @@ -182,6 +183,7 @@ static string const g_argAsmJson = g_strAsmJson; static string const g_argAssemble = g_strAssemble; static string const g_argAstCompactJson = g_strAstCompactJson; static string const g_argAstJson = g_strAstJson; +static string const g_argAstJsonNoCompile = g_strAstJsonNoCompile; static string const g_argBinary = g_strBinary; static string const g_argBinaryRuntime = g_strBinaryRuntime; static string const g_argCombinedJson = g_strCombinedJson; @@ -291,6 +293,7 @@ static bool needsHumanTargetedStdout(po::variables_map const& _args) g_argAsm, g_argAsmJson, g_argAstJson, + g_argAstJsonNoCompile, g_argBinary, g_argBinaryRuntime, g_argMetadata, @@ -837,6 +840,7 @@ Allowed options)", po::options_description outputComponents("Output Components"); outputComponents.add_options() (g_argAstJson.c_str(), "AST of all source files in JSON format.") + (g_argAstJsonNoCompile.c_str(), "AST of the single source file, no imports or compilation done, in JSON format.") (g_argAstCompactJson.c_str(), "AST of all source files in a compact JSON format.") (g_argAsm.c_str(), "EVM assembly of the contracts.") (g_argAsmJson.c_str(), "EVM assembly of the contracts in JSON format.") @@ -1136,6 +1140,7 @@ bool CommandLineInterface::processInput() } m_compiler = make_unique(fileReader); + m_compiler->setOnlyParsing(m_args.count(g_argAstJsonNoCompile)); unique_ptr formatter; if (m_args.count(g_argOldReporter)) @@ -1348,7 +1353,7 @@ void CommandLineInterface::handleAst(string const& _argStr) { string title; - if (_argStr == g_argAstJson) + if (_argStr == g_argAstJson || _argStr == g_argAstJsonNoCompile) title = "JSON AST:"; else if (_argStr == g_argAstCompactJson) title = "JSON AST (compact format):"; @@ -1374,7 +1379,7 @@ void CommandLineInterface::handleAst(string const& _argStr) gasCosts[it.first] += it.second; } - bool legacyFormat = !m_args.count(g_argAstCompactJson); + bool legacyFormat = !m_args.count(g_argAstCompactJson) && !m_args.count(g_argAstJsonNoCompile) ; if (m_args.count(g_argOutputDir)) { for (auto const& sourceCode: m_sourceCodes) @@ -1631,6 +1636,12 @@ void CommandLineInterface::outputCompilationResults() // do we need AST output? handleAst(g_argAstJson); handleAst(g_argAstCompactJson); + handleAst(g_argAstJsonNoCompile); + + if(m_args.count(g_argAstJsonNoCompile)) { + //Done here + return; + } if (!m_compiler->compilationSuccessful()) {