summaryrefslogtreecommitdiff
path: root/cpp/src/slice2js/JsUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/slice2js/JsUtil.cpp')
-rw-r--r--cpp/src/slice2js/JsUtil.cpp496
1 files changed, 446 insertions, 50 deletions
diff --git a/cpp/src/slice2js/JsUtil.cpp b/cpp/src/slice2js/JsUtil.cpp
index b33dfacb9d6..ec262b7c648 100644
--- a/cpp/src/slice2js/JsUtil.cpp
+++ b/cpp/src/slice2js/JsUtil.cpp
@@ -10,6 +10,7 @@
#include <JsUtil.h>
#include <Slice/Util.h>
#include <IceUtil/Functional.h>
+#include <IceUtil/StringUtil.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -27,6 +28,64 @@ using namespace Slice;
using namespace IceUtil;
using namespace IceUtilInternal;
+string
+Slice::relativePath(const string& p1, const string& p2)
+{
+ vector<string> tokens1;
+ vector<string> tokens2;
+
+ splitString(p1, "/\\", tokens1);
+ splitString(p2, "/\\", tokens2);
+
+ string f1 = tokens1.back();
+ string f2 = tokens2.back();
+
+ tokens1.pop_back();
+ tokens2.pop_back();
+
+ vector<string>::const_iterator i1 = tokens1.begin();
+ vector<string>::const_iterator i2 = tokens2.begin();
+
+ while(i1 != tokens1.end() && i2 != tokens2.end() && *i1 == *i2)
+ {
+ i1++;
+ i2++;
+ }
+
+ //
+ // Different volumes, relative path not possible.
+ //
+ if(i1 == tokens1.begin() && i2 == tokens2.begin())
+ {
+ return p1;
+ }
+
+ string newPath;
+ if(i2 == tokens2.end())
+ {
+ newPath += "./";
+ for (; i1 != tokens1.end(); ++i1)
+ {
+ newPath += *i1 + "/";
+ }
+ }
+ else
+ {
+ for(size_t i = tokens2.end() - i2; i > 0; i--)
+ {
+ newPath += "../";
+ }
+
+ for(; i1 != tokens1.end(); ++i1)
+ {
+ newPath += *i1 + "/";
+ }
+ }
+ newPath += f1;
+
+ return newPath;
+}
+
static string
lookupKwd(const string& name)
{
@@ -99,11 +158,71 @@ fixIds(const StringList& ids)
return newIds;
}
+string
+Slice::JsGenerator::getModuleMetadata(const TypePtr& type)
+{
+ static const char* builtinModuleTable[] =
+ {
+ "", // byte
+ "", // bool
+ "", // short
+ "", // int
+ "ice", // long
+ "", // float
+ "", // double
+ "", // string
+ "ice", // Ice.Value
+ "ice", // Ice.ObjectPrx
+ "", // LocalObject
+ "ice" // Ice.Object
+ };
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ return builtinModuleTable[builtin->kind()];
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ return getModuleMetadata(proxy ? ContainedPtr::dynamicCast(proxy->_class()->definition()) :
+ ContainedPtr::dynamicCast(type));
+}
+
+string
+Slice::JsGenerator::getModuleMetadata(const ContainedPtr& cont)
+{
+ //
+ // Traverse to the top-level module.
+ //
+ ModulePtr m;
+ ContainedPtr p = cont;
+ while (true)
+ {
+ if(ModulePtr::dynamicCast(p))
+ {
+ m = ModulePtr::dynamicCast(p);
+ }
+
+ ContainerPtr c = p->container();
+ p = ContainedPtr::dynamicCast(c); // This cast fails for Unit.
+ if(!p)
+ {
+ break;
+ }
+ }
+
+ const string prefix = "js:module:";
+ string value;
+ findMetaData(prefix, m->getMetaData(), value);
+ return value;
+}
+
bool
Slice::JsGenerator::isClassType(const TypePtr& type)
{
BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
- return (builtin && (builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindValue)) || ClassDeclPtr::dynamicCast(type);
+ return (builtin && (builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindValue)) ||
+ ClassDeclPtr::dynamicCast(type);
}
//
@@ -146,20 +265,182 @@ Slice::JsGenerator::fixId(const ContainedPtr& cont)
}
string
-Slice::JsGenerator::typeToString(const TypePtr& type)
+Slice::JsGenerator::importPrefix(const TypePtr& type,
+ const ContainedPtr& toplevel,
+ const vector<pair<string, string>>& imports)
+{
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ return typeToString(type, toplevel, imports, true);
+ }
+ else if(ProxyPtr::dynamicCast(type))
+ {
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ return importPrefix(ContainedPtr::dynamicCast(proxy->_class()->definition()), toplevel, imports);
+ }
+ else if(ContainedPtr::dynamicCast(type))
+ {
+ bool local = false;
+ if(toplevel)
+ {
+ if(ConstructedPtr::dynamicCast(toplevel))
+ {
+ local = ConstructedPtr::dynamicCast(toplevel)->isLocal();
+ }
+ else if(ClassDefPtr::dynamicCast(toplevel))
+ {
+ local = ClassDefPtr::dynamicCast(toplevel)->isLocal();
+ }
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl && cl->isInterface() && !local)
+ {
+ return "iceNS0.";
+ }
+ else
+ {
+ return importPrefix(ContainedPtr::dynamicCast(type), toplevel, imports);
+ }
+ }
+ return "";
+}
+
+string
+Slice::JsGenerator::importPrefix(const ContainedPtr& contained,
+ const ContainedPtr& toplevel,
+ const vector<pair<string, string>>& imports)
+{
+ string m1 = getModuleMetadata(contained);
+ string m2 = getModuleMetadata(toplevel);
+
+ string p;
+
+ if(m1.empty())
+ {
+ string p1 = contained->definitionContext()->filename();
+ string p2 = toplevel->definitionContext()->filename();
+
+ p = relativePath(p1, p2);
+
+ string::size_type pos = p.rfind('.');
+ if (pos != string::npos)
+ {
+ p.erase(pos);
+ }
+ }
+ else if(m1 == "ice" && m1 != m2)
+ {
+ return "iceNS0.";
+ }
+ else if(m1 != m2)
+ {
+ p = m1;
+ }
+
+ if(!p.empty())
+ {
+ for (vector<pair<string, string>>::const_iterator i = imports.begin(); i != imports.end(); ++i)
+ {
+ if (i->first == p)
+ {
+ return i->second + ".";
+ }
+ }
+ }
+
+ return "";
+}
+
+bool
+Slice::JsGenerator::findMetaData(const string& prefix, const StringList& metaData, string& value)
+{
+ for(StringList::const_iterator i = metaData.begin(); i != metaData.end(); i++)
+ {
+ string s = *i;
+ if(s.find(prefix) == 0)
+ {
+ value = s.substr(prefix.size());
+ return true;
+ }
+ }
+ return false;
+}
+
+string
+Slice::JsGenerator::importPrefix(const string& type, const ContainedPtr& toplevel)
+{
+ const string module = getModuleMetadata(toplevel);
+ return (type.find("Ice.") == 0 && module != "ice") ? "iceNS0." : "";
+}
+
+string
+Slice::JsGenerator::getUnqualified(const string& type, const string& scope, const string& importPrefix)
+{
+ if(importPrefix.empty())
+ {
+ const string localScope = getLocalScope(scope) + ".";
+ if(type.find(localScope) == 0)
+ {
+ string t = type.substr(localScope.size());
+ if(t.find(".") == string::npos)
+ {
+ return t;
+ }
+ }
+ }
+ return type;
+}
+
+string
+Slice::JsGenerator::typeToString(const TypePtr& type,
+ const ContainedPtr& toplevel,
+ const vector<pair<string, string>>& imports,
+ bool typescript,
+ bool definition)
{
if(!type)
{
return "void";
}
- static const char* builtinTable[] =
+ bool local = false;
+ if(toplevel)
+ {
+ if(ConstructedPtr::dynamicCast(toplevel))
+ {
+ local = ConstructedPtr::dynamicCast(toplevel)->isLocal();
+ }
+ else if(ClassDefPtr::dynamicCast(toplevel))
+ {
+ local = ClassDefPtr::dynamicCast(toplevel)->isLocal();
+ }
+ }
+
+ static const char* typeScriptBuiltinTable[] =
+ {
+ "number", // byte
+ "boolean", // bool
+ "number", // short
+ "number", // int
+ "Ice.Long", // long
+ "number", // float
+ "number", // double
+ "string",
+ "Ice.Object",
+ "Ice.ObjectPrx",
+ "Object",
+ "Ice.Value"
+ };
+
+ static const char* javaScriptBuiltinTable[] =
{
"Number", // byte
"Boolean", // bool
"Number", // short
"Number", // int
- "Number", // long
+ "Ice.Long", // long
"Number", // float
"Number", // double
"String",
@@ -172,39 +453,186 @@ Slice::JsGenerator::typeToString(const TypePtr& type)
BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
if(builtin)
{
- return builtinTable[builtin->kind()];
+ if(typescript)
+ {
+ int kind = (!local && builtin->kind() == Builtin::KindObject) ? Builtin::KindValue : builtin->kind();
+ ostringstream os;
+ if(getModuleMetadata(type) == "ice" && getModuleMetadata(toplevel) != "ice")
+ {
+ os << "iceNS0.";
+ }
+ os << getUnqualified(typeScriptBuiltinTable[kind], toplevel->scope(), "iceNS0.");
+ return os.str();
+ }
+ else
+ {
+ return javaScriptBuiltinTable[builtin->kind()];
+ }
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ string prefix;
+ ostringstream os;
+ if(typescript)
+ {
+ if(cl->isInterface() && !local)
+ {
+ prefix = importPrefix("Ice.Value", toplevel);
+ }
+ else
+ {
+ prefix = importPrefix(ContainedPtr::dynamicCast(cl), toplevel, imports);
+ }
+ }
+ os << prefix;
+ if(!prefix.empty() && typescript)
+ {
+ if(cl->isInterface() && !local)
+ {
+ os << getUnqualified("Ice.Value", toplevel->scope(), prefix);
+ }
+ else
+ {
+ os << getUnqualified(fixId(cl->scoped()), toplevel->scope(), prefix);
+ }
+ }
+ else
+ {
+ os << fixId(cl->scoped());
+ }
+ return os.str();
}
ProxyPtr proxy = ProxyPtr::dynamicCast(type);
if(proxy)
{
- return fixId(proxy->_class()->scoped() + "Prx");
- }
+ ostringstream os;
+ string prefix;
+ if(typescript)
+ {
+ prefix = importPrefix(ContainedPtr::dynamicCast(proxy->_class()->definition()), toplevel, imports);
+ os << prefix;
+ }
- SequencePtr seq = SequencePtr::dynamicCast(type);
- if(seq)
- {
- return typeToString(seq->type()) + "[]";
+ if(prefix.empty() && typescript)
+ {
+ os << getUnqualified(fixId(proxy->_class()->scoped() + "Prx"), toplevel->scope(), prefix);
+ }
+ else
+ {
+ os << fixId(proxy->_class()->scoped() + "Prx");
+ }
+ return os.str();
}
- DictionaryPtr d = DictionaryPtr::dynamicCast(type);
- if(d)
+ if(!typescript || definition)
{
- const TypePtr keyType = d->keyType();
- BuiltinPtr b = BuiltinPtr::dynamicCast(keyType);
- return ((b && b->kind() == Builtin::KindLong) || StructPtr::dynamicCast(keyType)) ? "Ice.HashMap" : "Map";
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if (seq)
+ {
+ BuiltinPtr b = BuiltinPtr::dynamicCast(seq->type());
+ if (b && b->kind() == Builtin::KindByte)
+ {
+ return "Uint8Array";
+ }
+ else
+ {
+ return typeToString(seq->type(), toplevel, imports, typescript) + "[]";
+ }
+ }
+
+ DictionaryPtr d = DictionaryPtr::dynamicCast(type);
+ if(d)
+ {
+ const TypePtr keyType = d->keyType();
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(keyType);
+ ostringstream os;
+ if ((builtin && builtin->kind() == Builtin::KindLong) || StructPtr::dynamicCast(keyType))
+ {
+ const string prefix = importPrefix("Ice.HashMap", toplevel);
+ os << prefix << getUnqualified("Ice.HashMap", toplevel->scope(), prefix);
+ }
+ else
+ {
+ os << "Map";
+ }
+
+ if (typescript)
+ {
+ os << "<"
+ << typeToString(keyType, toplevel, imports, true) << ", "
+ << typeToString(d->valueType(), toplevel, imports, true) << ">";
+ }
+ return os.str();
+ }
}
ContainedPtr contained = ContainedPtr::dynamicCast(type);
if(contained)
{
- return fixId(contained->scoped());
+ ostringstream os;
+ string prefix;
+ if(typescript)
+ {
+ prefix = importPrefix(contained, toplevel, imports);
+ os << prefix;
+ }
+
+ if(prefix.empty() && typescript)
+ {
+ os << getUnqualified(fixId(contained->scoped()), toplevel->scope(), prefix);
+ }
+ else
+ {
+ os << fixId(contained->scoped());
+ }
+ return os.str();
}
return "???";
}
string
+Slice::JsGenerator::typeToString(const TypePtr& type,
+ const ContainedPtr& toplevel,
+ const std::vector<std::pair<std::string, std::string>>& imports,
+ bool typeScript,
+ bool definition,
+ bool usealias)
+{
+ string t = typeToString(type, toplevel, imports, typeScript, definition);
+ if(usealias)
+ {
+ string m1 = getModuleMetadata(type);
+ string m2 = getModuleMetadata(toplevel);
+ if (!m1.empty() && m1 == m2)
+ {
+ // we are using the same module
+ return t;
+ }
+ string p = importPrefix(type, toplevel, imports);
+
+ //
+ // When using an import prefix we don't need an alias, prefixes use iceNSXX that is reserved
+ // name prefix
+ //
+ string::size_type i = t.find(".");
+ if(p.empty() && i != string::npos)
+ {
+ const string scoped = fixId(toplevel->scoped()) + ".";
+ if(scoped.find("." + t.substr(0, i + 1)) != string::npos)
+ {
+ replace(t.begin(), t.end(), '.', '_');
+ t = "iceA_" + t;
+ }
+ }
+ }
+ return t;
+}
+
+string
Slice::JsGenerator::getLocalScope(const string& scope, const string& separator)
{
assert(!scope.empty());
@@ -222,6 +650,7 @@ Slice::JsGenerator::getLocalScope(const string& scope, const string& separator)
{
fixedScope = scope;
}
+
if(fixedScope.empty())
{
return "";
@@ -243,39 +672,6 @@ Slice::JsGenerator::getLocalScope(const string& scope, const string& separator)
return result.str();
}
-string
-Slice::JsGenerator::getReference(const string& scope, const string& target)
-{
- //
- // scope and target should be fully-qualified symbols.
- //
- assert(!scope.empty() && scope[0] == ':' && !target.empty() && target[0] == ':');
-
- //
- // Check whether the target is in the given scope.
- //
- if(target.find(scope) == 0)
- {
- //
- // Remove scope from target, but keep the leading "::".
- //
- const string rem = target.substr(scope.size() - 2);
- assert(!rem.empty());
- const StringList ids = fixIds(splitScopedName(rem));
- stringstream result;
- result << getLocalScope(scope);
- for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i)
- {
- result << '.' << *i;
- }
- return result.str();
- }
- else
- {
- return fixId(target);
- }
-}
-
void
Slice::JsGenerator::writeMarshalUnmarshalCode(Output &out,
const TypePtr& type,