diff options
author | Jose <jose@zeroc.com> | 2019-02-26 00:13:38 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2019-02-26 00:14:51 +0100 |
commit | 668a3838e26b4e21a8635bd4ea39c3f7da96e2c8 (patch) | |
tree | 3a598d5e05995ef82787dfd262ace44511ca8db3 | |
parent | Float/double fixes and some linting (diff) | |
download | ice-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.cpp | 60 | ||||
-rw-r--r-- | cpp/src/Slice/Parser.h | 27 | ||||
-rw-r--r-- | cpp/src/slice2swift/Gen.cpp | 167 | ||||
-rw-r--r-- | cpp/src/slice2swift/Gen.h | 25 | ||||
-rw-r--r-- | cpp/src/slice2swift/Main.cpp | 8 | ||||
-rw-r--r-- | cpp/src/slice2swift/SwiftUtil.cpp | 254 | ||||
-rw-r--r-- | cpp/src/slice2swift/SwiftUtil.h | 40 |
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; }; } |