diff options
author | chriseth <c@ethdev.com> | 2016-07-01 16:14:50 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-07-21 01:45:43 +0800 |
commit | c55584d3e2da49674993972a129ef478ba6b4914 (patch) | |
tree | 419a4abda107edef1ed3df15398b6030b43bd1a8 /libsolidity/interface | |
parent | 980abfe52aac3161dc4f25574da83bfc6be977bf (diff) | |
download | dexon-solidity-c55584d3e2da49674993972a129ef478ba6b4914.tar.gz dexon-solidity-c55584d3e2da49674993972a129ef478ba6b4914.tar.zst dexon-solidity-c55584d3e2da49674993972a129ef478ba6b4914.zip |
Source location as part of AST.
Diffstat (limited to 'libsolidity/interface')
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 111 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 18 |
2 files changed, 127 insertions, 2 deletions
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 4776a4ce..f7982872 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -279,6 +279,28 @@ eth::AssemblyItems const* CompilerStack::runtimeAssemblyItems(string const& _con return currentContract.compiler ? &contract(_contractName).compiler->runtimeAssemblyItems() : nullptr; } +string const* CompilerStack::sourceMapping(string const& _contractName) const +{ + Contract const& c = contract(_contractName); + if (!c.sourceMapping) + { + if (auto items = assemblyItems(_contractName)) + c.sourceMapping.reset(new string(computeSourceMapping(*items))); + } + return c.sourceMapping.get(); +} + +string const* CompilerStack::runtimeSourceMapping(string const& _contractName) const +{ + Contract const& c = contract(_contractName); + if (!c.runtimeSourceMapping) + { + if (auto items = runtimeAssemblyItems(_contractName)) + c.runtimeSourceMapping.reset(new string(computeSourceMapping(*items))); + } + return c.runtimeSourceMapping.get(); +} + eth::LinkerObject const& CompilerStack::object(string const& _contractName) const { return contract(_contractName).object; @@ -315,6 +337,22 @@ Json::Value CompilerStack::streamAssembly(ostream& _outStream, string const& _co } } +vector<string> CompilerStack::sourceNames() const +{ + vector<string> names; + for (auto const& s: m_sources) + names.push_back(s.first); + return names; +} + +map<string, unsigned> CompilerStack::sourceIndices() const +{ + map<string, unsigned> indices; + for (auto const& s: m_sources) + indices[s.first] = indices.size(); + return indices; +} + string const& CompilerStack::interface(string const& _contractName) const { return metadata(_contractName, DocumentationType::ABIInterface); @@ -604,3 +642,76 @@ CompilerStack::Source const& CompilerStack::source(string const& _sourceName) co return it->second; } + +string CompilerStack::computeSourceMapping(eth::AssemblyItems const& _items) const +{ + string ret; + map<string, unsigned> sourceIndicesMap = sourceIndices(); + int prevStart = -1; + int prevLength = -1; + int prevSourceIndex = -1; + char prevJump = 0; + for (auto const& item: _items) + { + if (!ret.empty()) + ret += ";"; + + SourceLocation const& location = item.location(); + int length = location.start != -1 && location.end != -1 ? location.end - location.start : -1; + int sourceIndex = + location.sourceName && sourceIndicesMap.count(*location.sourceName) ? + sourceIndicesMap.at(*location.sourceName) : + -1; + char jump = '-'; + if (item.getJumpType() == eth::AssemblyItem::JumpType::IntoFunction) + jump = 'i'; + else if (item.getJumpType() == eth::AssemblyItem::JumpType::OutOfFunction) + jump = 'o'; + + unsigned components = 4; + if (jump == prevJump) + { + components--; + if (sourceIndex == prevSourceIndex) + { + components--; + if (length == prevLength) + { + components--; + if (location.start == prevStart) + components--; + } + } + } + + if (components-- > 0) + { + if (location.start != prevStart) + ret += std::to_string(location.start); + if (components-- > 0) + { + ret += ':'; + if (length != prevLength) + ret += std::to_string(length); + if (components-- > 0) + { + ret += ':'; + if (sourceIndex != prevSourceIndex) + ret += std::to_string(sourceIndex); + if (components-- > 0) + { + ret += ':'; + if (jump != prevJump) + ret += jump; + } + } + } + } + + prevStart = location.start; + prevLength = length; + prevSourceIndex = sourceIndex; + prevJump = jump; + } + return ret; +} diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 9d2aace4..a4b8447f 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -142,6 +142,12 @@ public: eth::AssemblyItems const* assemblyItems(std::string const& _contractName = "") const; /// @returns runtime contract assembly items eth::AssemblyItems const* runtimeAssemblyItems(std::string const& _contractName = "") const; + /// @returns the string that provides a mapping between bytecode and sourcecode or a nullptr + /// if the contract does not (yet) have bytecode. + std::string const* sourceMapping(std::string const& _contractName = "") const; + /// @returns the string that provides a mapping between runtime bytecode and sourcecode. + /// if the contract does not (yet) have bytecode. + std::string const* runtimeSourceMapping(std::string const& _contractName = "") const; /// @returns hash of the runtime bytecode for the contract, i.e. the code that is /// returned by the constructor or the zero-h256 if the contract still needs to be linked or /// does not have runtime code. @@ -153,6 +159,11 @@ public: /// Prerequisite: Successful compilation. Json::Value streamAssembly(std::ostream& _outStream, std::string const& _contractName = "", StringMap _sourceCodes = StringMap(), bool _inJsonFormat = false) const; + /// @returns the list of sources (paths) used + std::vector<std::string> sourceNames() const; + /// @returns a mapping assigning each source name its index inside the vector returned + /// by sourceNames(). + std::map<std::string, unsigned> sourceIndices() const; /// @returns a string representing the contract interface in JSON. /// Prerequisite: Successful call to parse or compile. std::string const& interface(std::string const& _contractName = "") const; @@ -196,9 +207,8 @@ private: { std::shared_ptr<Scanner> scanner; std::shared_ptr<SourceUnit> ast; - std::string interface; bool isLibrary = false; - void reset() { scanner.reset(); ast.reset(); interface.clear(); } + void reset() { scanner.reset(); ast.reset(); } }; struct Contract @@ -212,6 +222,8 @@ private: mutable std::unique_ptr<std::string const> solidityInterface; mutable std::unique_ptr<std::string const> userDocumentation; mutable std::unique_ptr<std::string const> devDocumentation; + mutable std::unique_ptr<std::string const> sourceMapping; + mutable std::unique_ptr<std::string const> runtimeSourceMapping; }; /// Loads the missing sources from @a _ast (named @a _path) using the callback @@ -236,6 +248,8 @@ private: Contract const& contract(std::string const& _contractName = "") const; Source const& source(std::string const& _sourceName = "") const; + std::string computeSourceMapping(eth::AssemblyItems const& _items) const; + struct Remapping { std::string context; |