summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2019-02-26 00:13:38 +0100
committerJose <jose@zeroc.com>2019-02-26 00:14:51 +0100
commit668a3838e26b4e21a8635bd4ea39c3f7da96e2c8 (patch)
tree3a598d5e05995ef82787dfd262ace44511ca8db3
parentFloat/double fixes and some linting (diff)
downloadice-668a3838e26b4e21a8635bd4ea39c3f7da96e2c8.tar.bz2
ice-668a3838e26b4e21a8635bd4ea39c3f7da96e2c8.tar.xz
ice-668a3838e26b4e21a8635bd4ea39c3f7da96e2c8.zip
Generate imports for types defined in separate Swift modules
-rw-r--r--cpp/src/Slice/Parser.cpp60
-rw-r--r--cpp/src/Slice/Parser.h27
-rw-r--r--cpp/src/slice2swift/Gen.cpp167
-rw-r--r--cpp/src/slice2swift/Gen.h25
-rw-r--r--cpp/src/slice2swift/Main.cpp8
-rw-r--r--cpp/src/slice2swift/SwiftUtil.cpp254
-rw-r--r--cpp/src/slice2swift/SwiftUtil.h40
7 files changed, 438 insertions, 143 deletions
diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp
index e49c20f1c50..52004688edf 100644
--- a/cpp/src/Slice/Parser.cpp
+++ b/cpp/src/Slice/Parser.cpp
@@ -19,6 +19,52 @@
using namespace std;
using namespace Slice;
+
+Slice::CompilerException::CompilerException(const char* file, int line, const string& r) :
+ IceUtil::Exception(file, line),
+ _reason(r)
+{
+}
+
+#ifndef ICE_CPP11_COMPILER
+Slice::CompilerException::~CompilerException() throw()
+{
+}
+#endif
+
+string
+Slice::CompilerException::ice_id() const
+{
+ return "::Slice::CompilerException";
+}
+
+void
+Slice::CompilerException::ice_print(ostream& out) const
+{
+ IceUtil::Exception::ice_print(out);
+ out << ": " << _reason;
+}
+
+#ifndef ICE_CPP11_MAPPING
+Slice::CompilerException*
+Slice::CompilerException::ice_clone() const
+{
+ return new CompilerException(*this);
+}
+#endif
+
+void
+Slice::CompilerException::ice_throw() const
+{
+ throw *this;
+}
+
+string
+Slice::CompilerException::reason() const
+{
+ return _reason;
+}
+
extern FILE* slice_in;
extern int slice_debug;
@@ -227,6 +273,20 @@ Slice::DefinitionContext::warning(WarningCategory category, const string& file,
}
}
+void
+Slice::DefinitionContext::error(const string& file, int line, const string& msg) const
+{
+ emitError(file, line, msg);
+ throw CompilerException(__FILE__, __LINE__, msg);
+}
+
+void
+Slice::DefinitionContext::error(const string& file, const string& line, const string& msg) const
+{
+ emitError(file, line, msg);
+ throw CompilerException(__FILE__, __LINE__, msg);
+}
+
bool
Slice::DefinitionContext::suppressWarning(WarningCategory category) const
{
diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h
index 77bbce0c6e1..a4bfccd6a2d 100644
--- a/cpp/src/Slice/Parser.h
+++ b/cpp/src/Slice/Parser.h
@@ -7,6 +7,7 @@
#include <IceUtil/Shared.h>
#include <IceUtil/Handle.h>
+#include <IceUtil/Exception.h>
#include <string>
#include <vector>
#include <list>
@@ -18,6 +19,29 @@
namespace Slice
{
+class CompilerException : public ::IceUtil::Exception
+{
+public:
+
+ CompilerException(const char*, int, const std::string&);
+#ifndef ICE_CPP11_COMPILER
+ ~CompilerException() throw();
+#endif
+ virtual std::string ice_id() const;
+ virtual void ice_print(std::ostream&) const;
+#ifndef ICE_CPP11_MAPPING
+ virtual CompilerException* ice_clone() const;
+#endif
+ virtual void ice_throw() const;
+
+ std::string reason() const;
+
+private:
+
+ static const char* _name;
+ const std::string _reason;
+};
+
#if defined(_WIN32) && !defined(__MINGW32__)
const IceUtil::Int64 Int32Max = 0x7fffffffi64;
@@ -241,6 +265,9 @@ public:
void warning(WarningCategory, const std::string&, int, const std::string&) const;
void warning(WarningCategory, const std::string&, const std::string&, const std::string&) const;
+ void error(const std::string&, int, const std::string&) const;
+ void error(const std::string&, const std::string&, const std::string&) const;
+
private:
bool suppressWarning(WarningCategory) const;
diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp
index 8706928df71..4fe18d8473c 100644
--- a/cpp/src/slice2swift/Gen.cpp
+++ b/cpp/src/slice2swift/Gen.cpp
@@ -69,6 +69,10 @@ Gen::generate(const UnitPtr& p)
{
SwiftGenerator::validateMetaData(p);
+ ImportVisitor importVisitor(_out);
+ p->visit(&importVisitor, false);
+ importVisitor.writeImports();
+
TypesVisitor typesVisitor(_out);
p->visit(&typesVisitor, false);
}
@@ -99,6 +103,167 @@ Gen::printHeader()
_out << "//\n";
}
+Gen::ImportVisitor::ImportVisitor(IceUtilInternal::Output& o) : out(o)
+{
+}
+
+bool
+Gen::ImportVisitor::visitModuleStart(const ModulePtr& p)
+{
+ //
+ // Always import Ice module first if not building Ice
+ //
+ if(UnitPtr::dynamicCast(p->container()) && _imports.empty())
+ {
+ string swiftModule = getSwiftModule(p);
+ if(swiftModule != "Ice")
+ {
+ _imports.push_back("Ice");
+ }
+ }
+ return true;
+}
+
+bool
+Gen::ImportVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ //
+ // Add imports required for base classes
+ //
+ ClassList bases = p->bases();
+ for(ClassList::const_iterator i = bases.begin(); i != bases.end(); ++i)
+ {
+ addImport(ContainedPtr::dynamicCast(*i), p);
+ }
+
+ //
+ // Add imports required for data members
+ //
+ const DataMemberList allDataMembers = p->allDataMembers();
+ for(DataMemberList::const_iterator i = allDataMembers.begin(); i != allDataMembers.end(); ++i)
+ {
+ addImport((*i)->type(), p);
+ }
+
+ //
+ // Add imports required for operation parameters and return type
+ //
+ const OperationList operationList = p->allOperations();
+ for(OperationList::const_iterator i = operationList.begin(); i != operationList.end(); ++i)
+ {
+ const TypePtr ret = (*i)->returnType();
+ if(ret && ret->definitionContext())
+ {
+ addImport(ret, p);
+ }
+
+ const ParamDeclList paramList = (*i)->parameters();
+ for(ParamDeclList::const_iterator j = paramList.begin(); j != paramList.end(); ++j)
+ {
+ addImport((*j)->type(), p);
+ }
+ }
+ return false;
+}
+
+bool
+Gen::ImportVisitor::visitStructStart(const StructPtr& p)
+{
+ //
+ // Add imports required for data members
+ //
+ const DataMemberList dataMembers = p->dataMembers();
+ for(DataMemberList::const_iterator i = dataMembers.begin(); i != dataMembers.end(); ++i)
+ {
+ addImport((*i)->type(), p);
+ }
+
+ return true;
+}
+
+bool
+Gen::ImportVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ //
+ // Add imports required for base exceptions
+ //
+ ExceptionPtr base = p->base();
+ if(base)
+ {
+ addImport(ContainedPtr::dynamicCast(base), p);
+ }
+
+ //
+ // Add imports required for data members
+ //
+ const DataMemberList allDataMembers = p->allDataMembers();
+ for(DataMemberList::const_iterator i = allDataMembers.begin(); i != allDataMembers.end(); ++i)
+ {
+ addImport((*i)->type(), p);
+ }
+ return true;
+}
+
+void
+Gen::ImportVisitor::visitSequence(const SequencePtr& seq)
+{
+ //
+ // Add import required for the sequence element type
+ //
+ addImport(seq->type(), seq);
+}
+
+
+void
+Gen::ImportVisitor::visitDictionary(const DictionaryPtr& dict)
+{
+ //
+ // Add imports required for the dictionary key and value types
+ //
+ addImport(dict->keyType(), dict);
+ addImport(dict->valueType(), dict);
+}
+
+void
+Gen::ImportVisitor::writeImports()
+{
+ for(vector<string>::const_iterator i = _imports.begin(); i != _imports.end(); ++i)
+ {
+ out << "import " << *i << nl;
+ }
+}
+
+void
+Gen::ImportVisitor::addImport(const TypePtr& definition, const ContainedPtr& toplevel)
+{
+ if(!BuiltinPtr::dynamicCast(definition))
+ {
+ ModulePtr m1 = getTopLevelModule(definition);
+ ModulePtr m2 = getTopLevelModule(toplevel);
+
+ string swiftM1 = getSwiftModule(m1);
+ string swiftM2 = getSwiftModule(m2);
+ if(swiftM1 != swiftM2 && find(_imports.begin(), _imports.end(), swiftM1) == _imports.end())
+ {
+ _imports.push_back(swiftM1);
+ }
+ }
+}
+
+void
+Gen::ImportVisitor::addImport(const ContainedPtr& definition, const ContainedPtr& toplevel)
+{
+ ModulePtr m1 = getTopLevelModule(definition);
+ ModulePtr m2 = getTopLevelModule(toplevel);
+
+ string swiftM1 = getSwiftModule(m1);
+ string swiftM2 = getSwiftModule(m2);
+ if(swiftM1 != swiftM2 && find(_imports.begin(), _imports.end(), swiftM1) == _imports.end())
+ {
+ _imports.push_back(swiftM1);
+ }
+}
+
Gen::TypesVisitor::TypesVisitor(IceUtilInternal::Output& o) : out(o)
{
}
@@ -223,7 +388,7 @@ bool Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
out << sb;
if(!p->dataMembers().empty())
{
- writeDataMembers(out, p->dataMembers(), true);
+ writeDataMembers(out, p->dataMembers());
writeInitializer(out, p->dataMembers(), p->allDataMembers());
}
out << eb << nl;
diff --git a/cpp/src/slice2swift/Gen.h b/cpp/src/slice2swift/Gen.h
index 79e8eb62be4..414d5fb725c 100644
--- a/cpp/src/slice2swift/Gen.h
+++ b/cpp/src/slice2swift/Gen.h
@@ -38,6 +38,30 @@ private:
std::vector<std::string> _includePaths;
std::string _fileBase;
+ class ImportVisitor : public SwiftGenerator, public ParserVisitor
+ {
+ public:
+
+ ImportVisitor(IceUtilInternal::Output&);
+
+ virtual bool visitModuleStart(const ModulePtr&);
+ virtual bool visitClassDefStart(const ClassDefPtr&);
+ virtual bool visitStructStart(const StructPtr&);
+ virtual bool visitExceptionStart(const ExceptionPtr&);
+ virtual void visitSequence(const SequencePtr&);
+ virtual void visitDictionary(const DictionaryPtr&);
+
+ void writeImports();
+
+ private:
+
+ void addImport(const TypePtr&, const ContainedPtr&);
+ void addImport(const ContainedPtr&, const ContainedPtr&);
+
+ IceUtilInternal::Output& out;
+ std::vector< std::string> _imports;
+ };
+
class TypesVisitor : public SwiftGenerator, public ParserVisitor
{
@@ -54,6 +78,7 @@ private:
virtual void visitConst(const ConstPtr&);
private:
+
IceUtilInternal::Output& out;
};
};
diff --git a/cpp/src/slice2swift/Main.cpp b/cpp/src/slice2swift/Main.cpp
index b2c471eb328..2a045087260 100644
--- a/cpp/src/slice2swift/Main.cpp
+++ b/cpp/src/slice2swift/Main.cpp
@@ -301,7 +301,13 @@ compile(const vector<string>& argv)
u->destroy();
consoleErr << argv[0] << ": error: " << ex.reason() << endl;
status = EXIT_FAILURE;
- FileTracker::instance()->error();
+ break;
+ }
+ catch(const Slice::CompilerException&)
+ {
+ FileTracker::instance()->cleanup();
+ u->destroy();
+ status = EXIT_FAILURE;
break;
}
}
diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp
index c7dd5c5f42c..085a3bc46d9 100644
--- a/cpp/src/slice2swift/SwiftUtil.cpp
+++ b/cpp/src/slice2swift/SwiftUtil.cpp
@@ -108,65 +108,81 @@ fixIds(const StringList& ids)
}
-SwiftGenerator::ModuleMap SwiftGenerator::_modules;
-
-void
-SwiftGenerator::validateMetaData(const UnitPtr& u)
+string
+Slice::getSwiftModule(const ModulePtr& module, string& swiftPrefix)
{
- MetaDataVisitor visitor;
- u->visit(&visitor, true);
-}
+ const string modulePrefix = "swift:module:";
-bool
-SwiftGenerator::addModule(const ModulePtr& m, const string& module, const string& name)
-{
- string scoped = m->scoped();
- ModuleMap::const_iterator i = _modules.find(scoped);
- if(i != _modules.end())
+ string swiftModule;
+
+ if(module->findMetaData(modulePrefix, swiftModule))
{
- if(i->second.module != module || i->second.name != name)
+ swiftModule = swiftModule.substr(modulePrefix.size());
+
+ size_t pos = swiftModule.find(':');
+ if(pos != string::npos)
{
- return false;
+ swiftPrefix = swiftModule.substr(pos + 1);
+ swiftModule = swiftModule.substr(0, pos);
}
}
else
{
- ModulePrefix mp;
- mp.m = m;
- mp.module = module;
- mp.name = name;
- _modules[scoped] = mp;
+ swiftModule = module->name();
+ swiftPrefix = "";
}
- return true;
-}
-
-SwiftGenerator::ModulePrefix
-SwiftGenerator::modulePrefix(const ModulePtr& m)
-{
- return _modules[m->scoped()];
+ return swiftModule;
}
string
-SwiftGenerator::moduleName(const ModulePtr& m)
+Slice::getSwiftModule(const ModulePtr& module)
{
- return _modules[m->scoped()].name;
+ string prefix;
+ return getSwiftModule(module, prefix);
}
ModulePtr
-SwiftGenerator::findModule(const ContainedPtr& cont)
+Slice::getTopLevelModule(const ContainedPtr& cont)
{
- ModulePtr m = ModulePtr::dynamicCast(cont);
- ContainerPtr container = cont->container();
- while(container && !m)
+ //
+ // Traverse to the top-level module.
+ //
+ ModulePtr m;
+ ContainedPtr p = cont;
+ while(true)
{
- ContainedPtr contained = ContainedPtr::dynamicCast(container);
- container = contained->container();
- m = ModulePtr::dynamicCast(contained);
+ if(ModulePtr::dynamicCast(p))
+ {
+ m = ModulePtr::dynamicCast(p);
+ }
+
+ ContainerPtr c = p->container();
+ p = ContainedPtr::dynamicCast(c); // This cast fails for Unit.
+ if(!p)
+ {
+ break;
+ }
}
- assert(m);
return m;
}
+ModulePtr
+Slice::getTopLevelModule(const TypePtr& type)
+{
+ assert(ProxyPtr::dynamicCast(type) || ContainedPtr::dynamicCast(type));
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ return getTopLevelModule(proxy ? ContainedPtr::dynamicCast(proxy->_class()->definition()) :
+ ContainedPtr::dynamicCast(type));
+}
+
+void
+SwiftGenerator::validateMetaData(const UnitPtr& u)
+{
+ MetaDataVisitor visitor;
+ u->visit(&visitor, true);
+}
+
string
SwiftGenerator::getLocalScope(const string& scope, const string& separator)
{
@@ -348,7 +364,7 @@ SwiftGenerator::fixIdent(const std::string& ident)
std::string
SwiftGenerator::fixName(const ContainedPtr& cont)
{
- return moduleName(findModule(cont)) + cont->name();
+ return cont->name();
}
//
@@ -797,12 +813,83 @@ SwiftGenerator::writeMarshalUnmarshalCode(IceUtilInternal::Output& out, const Cl
}
}
-const string SwiftGenerator::MetaDataVisitor::_msg= "ignoring invalid metadata";
-
bool
SwiftGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p)
{
- validate(p);
+ if(UnitPtr::dynamicCast(p->container()))
+ {
+ const UnitPtr ut = p->unit();
+ const DefinitionContextPtr dc = ut->findDefinitionContext(p->file());
+ assert(dc);
+
+ // top-level module
+ ModulePtr m = ModulePtr::dynamicCast(p);
+ const string modulePrefix = "swift:module:";
+
+ string swiftModule;
+ string swiftPrefix;
+
+ if(m->findMetaData(modulePrefix, swiftModule))
+ {
+ swiftModule = swiftModule.substr(modulePrefix.size());
+
+ size_t pos = swiftModule.find(':');
+ if(pos != string::npos)
+ {
+ swiftPrefix = swiftModule.substr(pos + 1);
+ swiftModule = swiftModule.substr(0, pos);
+ }
+ }
+ else
+ {
+ swiftModule = m->name();
+ }
+
+ const string filename = m->definitionContext()->filename();
+ ModuleMap::const_iterator current = _modules.find(filename);
+
+ if(current == _modules.end())
+ {
+ _modules[filename] = swiftModule;
+ }
+ else if(current->second != swiftModule)
+ {
+ ostringstream os;
+ os << "invalid module mapping:\n Slice module `" << m->scoped() << "' should be map to Swift module `"
+ << current->second << "'" << endl;
+ dc->error(p->file(), p->line(), os.str());
+ }
+
+ ModulePrefix::iterator prefixes = _prefixes.find(swiftModule);
+ if(prefixes == _prefixes.end())
+ {
+ ModuleMap mappings;
+ mappings[p->name()] = swiftPrefix;
+ _prefixes[swiftModule] = mappings;
+ }
+ else
+ {
+ current = prefixes->second.find(p->name());
+ if(current == prefixes->second.end())
+ {
+ prefixes->second[p->name()] = swiftPrefix;
+ }
+ else
+ {
+ ostringstream os;
+ os << "invalid module prefix:\n Slice module `" << m->scoped() << "' is already using";
+ if(current->second.empty())
+ {
+ os << " no prefix " << endl;
+ }
+ else
+ {
+ os << " a different Swift module prefix `" << current->second << "'" << endl;
+ }
+ dc->error(p->file(), p->line(), os.str());
+ }
+ }
+ }
return true;
}
@@ -825,21 +912,25 @@ SwiftGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p)
validate(p);
return true;
}
+
void
SwiftGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p)
{
validate(p);
}
+
void
SwiftGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p)
{
validate(p);
}
+
void
SwiftGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p)
{
validate(p);
}
+
void
SwiftGenerator::MetaDataVisitor::visitConst(const ConstPtr& p)
{
@@ -847,85 +938,6 @@ SwiftGenerator::MetaDataVisitor::visitConst(const ConstPtr& p)
}
void
-SwiftGenerator::MetaDataVisitor::validate(const ContainedPtr& cont)
+SwiftGenerator::MetaDataVisitor::validate(const ContainedPtr&)
{
- ModulePtr m = ModulePtr::dynamicCast(cont);
- if(m)
- {
- bool error = false;
- bool found = false;
- StringList meta = cont->getMetaData();
-
- for(StringList::iterator p = meta.begin(); p != meta.end();)
- {
- string s = *p++;
-
- // Module metadata must be of the form swift:module:{{modulename}}:{{prefix}}
- const string modulePrefix = "swift:module:";
- string module;
- string prefix;
- if(s.find(modulePrefix) == 0)
- {
- found = true;
- string metadata = trim(s.substr(modulePrefix.size()));
-
- size_t pos = metadata.find(":");
- if(pos != string::npos)
- {
- module = metadata.substr(0, pos);
- prefix = metadata.substr(pos+1, metadata.size());
- }
-
- if(module.empty() || prefix.empty())
- {
- m->definitionContext()->warning(InvalidMetaData, m->definitionContext()->filename(),
- m->line(), _msg + " `" + s + "'");
- meta.remove(s);
- error = true;
- }
- else
- {
- if(!addModule(m, module, prefix))
- {
- modulePrefixError(m, s);
- }
- }
- }
- // else
- // {
- // m->definitionContext()->warning(InvalidMetaData, m->definitionContext()->filename(),
- // m->line(), _msg + " `" + s + "'");
- // meta.remove(s);
- // error = true;
- // }
- }
- m->setMetaData(meta);
- }
-}
-
-void
-SwiftGenerator::MetaDataVisitor::modulePrefixError(const ModulePtr& m, const std::string& metadata)
-{
- string file = m->definitionContext()->filename();
- string line = m->line();
- ModulePrefix mp = modulePrefix(m);
- string old_file = mp.m->definitionContext()->filename();
- string old_line = mp.m->line();
- ostringstream os;
- if(!metadata.empty())
- {
- os << _msg << " `" << metadata << "': ";
- }
- os << "inconsistent module prefix previously defined ";
- if(old_file != file)
- {
- os << "in " << old_file << ":";
- }
- else
- {
- os << "at line ";
- }
- os << line;
- os << " as `" << mp.name << "'" << endl;
- m->definitionContext()->warning(All, file, line, os.str());
}
diff --git a/cpp/src/slice2swift/SwiftUtil.h b/cpp/src/slice2swift/SwiftUtil.h
index 4cdfbd01e80..98863020ffb 100644
--- a/cpp/src/slice2swift/SwiftUtil.h
+++ b/cpp/src/slice2swift/SwiftUtil.h
@@ -16,6 +16,11 @@
namespace Slice
{
+std::string getSwiftModule(const ModulePtr&, std::string&);
+std::string getSwiftModule(const ModulePtr&);
+ModulePtr getTopLevelModule(const ContainedPtr&);
+ModulePtr getTopLevelModule(const TypePtr&);
+
class SwiftGenerator : private IceUtil::noncopyable
{
public:
@@ -26,19 +31,6 @@ public:
protected:
- struct ModulePrefix
- {
- ModulePtr m;
- std::string module;
- std::string name;
- };
-
- static bool addModule(const ModulePtr&, const std::string&, const std::string&);
- static ModulePrefix modulePrefix(const ModulePtr&);
- static std::string moduleName(const ModulePtr&);
- static ModulePtr findModule(const ContainedPtr&);
- static void modulePrefixError(const ModulePtr&, const std::string&);
-
std::string getLocalScope(const std::string&, const std::string& = ".");
std::string typeToString(const TypePtr&, const ContainedPtr& = 0);
std::string typeToProxyImpl(const TypePtr&);
@@ -67,6 +59,7 @@ protected:
private:
+
class MetaDataVisitor : public ParserVisitor
{
public:
@@ -81,17 +74,24 @@ private:
virtual void visitConst(const ConstPtr&);
private:
+
void validate(const ContainedPtr&);
- static void modulePrefixError(const ModulePtr&, const std::string&);
+
+ typedef std::map<std::string, std::string> ModuleMap;
+ typedef std::map<std::string, ModuleMap> ModulePrefix;
+
+ //
+ // Each Slice unit has to map all top-level modules to a single Swift module
+ //
+ ModuleMap _modules;
+
+ //
+ // With a given Swift module a Slice module has to map to a single prefix
+ //
+ ModulePrefix _prefixes;
static const std::string _msg;
};
-
- //
- // Map of module scoped name to ModulePtr. Used to verify that objc:prefix metadata directives are consistent.
- //
- typedef std::map<std::string, ModulePrefix> ModuleMap;
- static ModuleMap _modules;
};
}