aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-12-10 00:35:20 +0800
committerchriseth <c@ethdev.com>2015-12-10 02:21:02 +0800
commitf8228e8ab116799a1b28ea9cbb01fdd7342b395c (patch)
tree182796217c88cdfa49b2dedf3c192f75dd7a8052
parent7cb7818ceaf8f2e50cdd66b33a4e0d17c2a0e879 (diff)
downloaddexon-solidity-f8228e8ab116799a1b28ea9cbb01fdd7342b395c.tar.gz
dexon-solidity-f8228e8ab116799a1b28ea9cbb01fdd7342b395c.tar.zst
dexon-solidity-f8228e8ab116799a1b28ea9cbb01fdd7342b395c.zip
Relative paths in import directives.
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp14
-rw-r--r--libsolidity/ast/AST.cpp7
-rw-r--r--libsolidity/ast/AST.h1
-rw-r--r--libsolidity/ast/ASTAnnotations.h6
-rw-r--r--libsolidity/interface/CompilerStack.cpp29
-rw-r--r--libsolidity/interface/CompilerStack.h2
-rw-r--r--test/libsolidity/Imports.cpp17
7 files changed, 67 insertions, 9 deletions
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 907d703c..ca866ddb 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -71,19 +71,25 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
for (auto const& node: _sourceUnit.nodes())
if (auto imp = dynamic_cast<ImportDirective const*>(node.get()))
{
- if (!_sourceUnits.count(imp->identifier()))
+ string const& path = imp->annotation().absolutePath;
+ if (!_sourceUnits.count(path))
{
- reportDeclarationError(node->location(), "Import \"" + imp->identifier() + "\" not found.");
+ reportDeclarationError( node->location(),
+ "Import \"" +
+ path +
+ "\" (referenced as \"" +
+ imp->identifier() +
+ "\") not found."
+ );
error = true;
}
else
{
- auto scope = m_scopes.find(_sourceUnits.at(imp->identifier()));
+ auto scope = m_scopes.find(_sourceUnits.at(path));
solAssert(scope != end(m_scopes), "");
for (auto const& nameAndDeclaration: scope->second->declarations())
for (auto const& declaration: nameAndDeclaration.second)
target.registerDeclaration(*declaration, &nameAndDeclaration.first);
-
}
}
return !error;
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 6006d441..701202f9 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -56,6 +56,13 @@ Error ASTNode::createTypeError(string const& _description) const
return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description);
}
+ImportAnnotation& ImportDirective::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new ImportAnnotation();
+ return static_cast<ImportAnnotation&>(*m_annotation);
+}
+
map<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions() const
{
auto exportedFunctionList = interfaceFunctionList();
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 446088ad..75cb9ab2 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -142,6 +142,7 @@ public:
virtual void accept(ASTConstVisitor& _visitor) const override;
ASTString const& identifier() const { return *m_identifier; }
+ virtual ImportAnnotation& annotation() const override;
private:
ASTPointer<ASTString> m_identifier;
diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h
index 4e0187cf..0bc91c60 100644
--- a/libsolidity/ast/ASTAnnotations.h
+++ b/libsolidity/ast/ASTAnnotations.h
@@ -54,6 +54,12 @@ struct DocumentedAnnotation
std::multimap<std::string, DocTag> docTags;
};
+struct ImportAnnotation: ASTAnnotation
+{
+ /// The absolute path of the source unit to import.
+ std::string absolutePath;
+};
+
struct TypeDeclarationAnnotation: ASTAnnotation
{
/// The name of this type, prefixed by proper namespaces if globally accessible.
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index 38fe5956..7f097523 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -22,6 +22,7 @@
*/
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
#include <libsolidity/ast/AST.h>
#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/parsing/Parser.h>
@@ -367,7 +368,7 @@ void CompilerStack::resolveImports()
vector<Source const*> sourceOrder;
set<Source const*> sourcesSeen;
- function<void(Source const*)> toposort = [&](Source const* _source)
+ function<void(string const&, Source const*)> toposort = [&](string const& _sourceName, Source const* _source)
{
if (sourcesSeen.count(_source))
return;
@@ -375,26 +376,44 @@ void CompilerStack::resolveImports()
for (ASTPointer<ASTNode> const& node: _source->ast->nodes())
if (ImportDirective const* import = dynamic_cast<ImportDirective*>(node.get()))
{
- string const& id = import->identifier();
- if (!m_sources.count(id))
+ string path = absolutePath(import->identifier(), _sourceName);
+ import->annotation().absolutePath = path;
+ if (!m_sources.count(path))
BOOST_THROW_EXCEPTION(
Error(Error::Type::ParserError)
<< errinfo_sourceLocation(import->location())
<< errinfo_comment("Source not found.")
);
- toposort(&m_sources[id]);
+ toposort(path, &m_sources[path]);
}
sourceOrder.push_back(_source);
};
for (auto const& sourcePair: m_sources)
if (!sourcePair.second.isLibrary)
- toposort(&sourcePair.second);
+ toposort(sourcePair.first, &sourcePair.second);
swap(m_sourceOrder, sourceOrder);
}
+string CompilerStack::absolutePath(string const& _path, string const& _reference) const
+{
+ // Anything that does not start with `.` is an absolute path.
+ if (_path.empty() || _path.front() != '.')
+ return _path;
+ using path = boost::filesystem::path;
+ path p(_path);
+ path result(_reference);
+ result.remove_filename();
+ for (path::iterator it = p.begin(); it != p.end(); ++it)
+ if (*it == "..")
+ result = result.parent_path();
+ else if (*it != ".")
+ result /= *it;
+ return result.string();
+}
+
void CompilerStack::compileContract(
bool _optimize,
unsigned _runs,
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 0473d58b..3e6dc456 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -199,6 +199,8 @@ private:
};
void resolveImports();
+ /// @returns the absolute path corresponding to @a _path relative to @a _reference.
+ std::string absolutePath(std::string const& _path, std::string const& _reference) const;
/// Compile a single contract and put the result in @a _compiledContracts.
void compileContract(
bool _optimize,
diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp
index b5ff0c54..ab8e2257 100644
--- a/test/libsolidity/Imports.cpp
+++ b/test/libsolidity/Imports.cpp
@@ -76,6 +76,23 @@ BOOST_AUTO_TEST_CASE(circular_import)
BOOST_CHECK(c.compile());
}
+BOOST_AUTO_TEST_CASE(relative_import)
+{
+ CompilerStack c;
+ c.addSource("a", "import \"./dir/b\"; contract A is B {}");
+ c.addSource("dir/b", "contract B {}");
+ c.addSource("dir/c", "import \"../a\"; contract C is A {}");
+ BOOST_CHECK(c.compile());
+}
+
+BOOST_AUTO_TEST_CASE(relative_import_multiplex)
+{
+ CompilerStack c;
+ c.addSource("a", "contract A {}");
+ c.addSource("dir/a/b/c", "import \"../../.././a\"; contract B is A {}");
+ BOOST_CHECK(c.compile());
+}
+
BOOST_AUTO_TEST_SUITE_END()
}