Browse Source

Adding interface mixins

Josh Engebretson 9 years ago
parent
commit
3a67746912

+ 1 - 1
Script/AtomicNET/AtomicNET/IO/Deserializer.cs

@@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
 namespace AtomicEngine
 {
 
-    public interface Deserializer
+    public partial interface Deserializer
     {
         IntPtr NativeInstance { get; }
     }

+ 1 - 1
Script/AtomicNET/AtomicNET/IO/Serializer.cs

@@ -2,7 +2,7 @@ using System;
 namespace AtomicEngine
 {
 
-    public interface Serializer
+    public partial interface Serializer
     {
         IntPtr NativeInstance { get; }
 

+ 56 - 23
Source/ToolCore/JSBind/CSharp/CSClassWriter.cpp

@@ -50,6 +50,9 @@ void CSClassWriter::WriteNativeFunctions(String& source)
         if (function->Skip())
             continue;
 
+        if (klass_->IsInterface() && function->IsConstructor())
+            continue;
+
         if (function->IsDestructor())
             continue;
 
@@ -71,8 +74,11 @@ void CSClassWriter::GenerateNativeSource(String& sourceOut)
 
     JSBPackage* package = klass_->GetPackage();
 
-    source.AppendWithFormat("ATOMIC_EXPORT_API ClassID csb_%s_%s_GetClassIDStatic()\n{\n", package->GetName().CString(),klass_->GetName().CString());
-    source.AppendWithFormat("   return %s::GetClassIDStatic();\n}\n\n", klass_->GetNativeName().CString());
+    if (!klass_->IsInterface())
+    {
+        source.AppendWithFormat("ATOMIC_EXPORT_API ClassID csb_%s_%s_GetClassIDStatic()\n{\n", package->GetName().CString(), klass_->GetName().CString());
+        source.AppendWithFormat("   return %s::GetClassIDStatic();\n}\n\n", klass_->GetNativeName().CString());
+    }
 
     WriteNativeFunctions(source);
 
@@ -116,7 +122,7 @@ void CSClassWriter::WriteManagedProperties(String& sourceOut)
             if (!fType)
                 continue;
 
-            String line = "public ";
+            String line = klass_->IsInterface() ? "" : "public ";
 
             JSBClass* baseClass = klass_->GetBaseClass();
             if (baseClass)
@@ -137,32 +143,47 @@ void CSClassWriter::WriteManagedProperties(String& sourceOut)
 
             if (prop->getter_)
             {
-                source += IndentLine("get\n");
-                source += IndentLine("{\n");
+                if (klass_->IsInterface())
+                {
+                    source += IndentLine("get;\n");
+                }
+                else
+                {
+                    source += IndentLine("get\n");
+                    source += IndentLine("{\n");
 
-                Indent();
+                    Indent();
 
-                source += IndentLine(ToString("return %s();\n", prop->getter_->GetName().CString()));
+                    source += IndentLine(ToString("return %s();\n", prop->getter_->GetName().CString()));
 
-                Dedent();
+                    Dedent();
 
-                source += IndentLine("}\n");
+                    source += IndentLine("}\n");
+                }
             }
 
             if (prop->setter_)
             {
-                source += IndentLine("set\n");
-                source += IndentLine("{\n");
+                if (klass_->IsInterface())
+                {
+                    source += IndentLine("set;\n");
+                }
+                else
+                {
+                    source += IndentLine("set\n");
+                    source += IndentLine("{\n");
 
-                Indent();
+                    Indent();
 
-                source += IndentLine(ToString("%s(value);\n", prop->setter_->GetName().CString()));
+                    source += IndentLine(ToString("%s(value);\n", prop->setter_->GetName().CString()));
 
-                Dedent();
+                    Dedent();
 
-                source += IndentLine("}\n");
-            }
+                    source += IndentLine("}\n");
 
+                }
+
+            }
 
             Dedent();
 
@@ -223,7 +244,12 @@ void CSClassWriter::GenerateManagedSource(String& sourceOut)
     }
     else
     {
-        line = ToString("public partial class %s%s\n", klass_->GetName().CString(), klass_->IsGeneric() ? "<T>" : "");
+        String classString = "class";
+
+        if (klass_->IsInterface())
+            classString = "interface";
+
+        line = ToString("public partial %s %s%s\n", classString.CString(), klass_->GetName().CString(), klass_->IsGeneric() ? "<T>" : "");
     }
 
 
@@ -241,11 +267,15 @@ void CSClassWriter::GenerateManagedSource(String& sourceOut)
     // line = "[SuppressUnmanagedCodeSecurity]\n";
     // source += IndentLine(line);
 
-    line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
-    source += IndentLine(line);
-    line = ToString("public static extern IntPtr csb_%s_%s_GetClassIDStatic();\n", package->GetName().CString(),klass_->GetName().CString());
-    source += IndentLine(line);
-    source += "\n";
+    if (!klass_->IsInterface())
+    {
+        line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
+        source += IndentLine(line);
+        line = ToString("public static extern IntPtr csb_%s_%s_GetClassIDStatic();\n", package->GetName().CString(), klass_->GetName().CString());
+        source += IndentLine(line);
+        source += "\n";
+    }
+
     Dedent();
 
     // managed functions
@@ -259,6 +289,9 @@ void CSClassWriter::GenerateManagedSource(String& sourceOut)
         if (function->Skip())
             continue;
 
+        if (klass_->IsInterface() && function->IsConstructor())
+            continue;
+
         if (function->IsDestructor())
             continue;
 
@@ -272,7 +305,7 @@ void CSClassWriter::GenerateManagedSource(String& sourceOut)
 
     // There are some constructors being skipped (like HTTPRequest as it uses a vector of strings in args)
     // Make sure we have at least a IntPtr version
-    if (!CSFunctionWriter::GetWroteConstructor() && klass_->GetName() != "RefCounted")
+    if (!klass_->IsInterface() && !CSFunctionWriter::GetWroteConstructor() && klass_->GetName() != "RefCounted")
     {
         ATOMIC_LOGINFOF("WARNING: %s class didn't write a constructor, filling in generated native constructor", klass_->GetName().CString());
 

+ 48 - 32
Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp

@@ -364,6 +364,12 @@ void CSFunctionWriter::WriteDefaultStructParameters(String& source)
 
 void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
 {
+    JSBClass* klass = function_->GetClass();
+    JSBPackage* package = klass->GetPackage();
+
+    if (klass->IsInterface())
+        return;
+
     source += "\n";
 
     // CoreCLR has pinvoke security demand code commented out, so we do not (currently) need this optimization:
@@ -374,9 +380,6 @@ void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source)
     String line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
     source += IndentLine(line);
 
-    JSBClass* klass = function_->GetClass();
-    JSBPackage* package = klass->GetPackage();
-
     String returnType = CSTypeHelper::GetPInvokeTypeString(function_->GetReturnType());
 
     // handled by out parameter
@@ -696,7 +699,7 @@ void CSFunctionWriter::WriteManagedFunction(String& source)
 
     GenManagedFunctionParameters(sig);
 
-    String line = "public ";
+    String line = klass->IsInterface() ? "" : "public ";
 
     if (function_->IsStatic())
     {
@@ -718,10 +721,20 @@ void CSFunctionWriter::WriteManagedFunction(String& source)
         }
     }
 
-    if (!marked && function_->IsVirtual())
+    if (!marked && function_->IsVirtual() && !klass->IsInterface())
         line += "virtual ";
 
-    line += ToString("%s %s (%s)\n", returnType.CString(), function_->GetName().CString(), sig.CString());
+    line += ToString("%s %s (%s)", returnType.CString(), function_->GetName().CString(), sig.CString());
+
+    if (klass->IsInterface())
+    {
+        // If we're an interface we have no implementation
+        line += ";\n\n";
+        source += IndentLine(line);
+        return;
+    }
+    else
+        line += "\n";
 
     source += IndentLine(line);
 
@@ -828,6 +841,7 @@ void CSFunctionWriter::WriteManagedFunction(String& source)
 
 void CSFunctionWriter::GenerateManagedSource(String& sourceOut)
 {
+    JSBClass* klass = function_->GetClass();
 
     String source = "";
 
@@ -854,47 +868,49 @@ void CSFunctionWriter::GenerateManagedSource(String& sourceOut)
 
     WriteManagedPInvokeFunctionSignature(source);
 
-    // data marshaller
-    if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
+    if (!klass->IsInterface())
     {
-        if (function_->GetReturnClass())
+        // data marshaller
+        if (function_->GetReturnType() && !CSTypeHelper::IsSimpleReturn(function_->GetReturnType()))
         {
-            JSBClass* retClass = function_->GetReturnClass();
-
-            if (retClass->IsNumberArray())
+            if (function_->GetReturnClass())
             {
-                JSBClass* klass = function_->GetClass();
-                String managedType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
-                String marshal = "private ";
+                JSBClass* retClass = function_->GetReturnClass();
 
-                if (function_->IsStatic())
-                    marshal += "static ";
+                if (retClass->IsNumberArray())
+                {
+                    String managedType = CSTypeHelper::GetManagedTypeString(function_->GetReturnType());
+                    String marshal = "private ";
 
-                marshal += managedType + " ";
+                    if (function_->IsStatic())
+                        marshal += "static ";
 
-                marshal += ToString("%s%s%uReturnValue = new %s();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), managedType.CString());
+                    marshal += managedType + " ";
 
-                sourceOut += IndentLine(marshal);
+                    marshal += ToString("%s%s%uReturnValue = new %s();\n", klass->GetName().CString(), function_->GetName().CString(), function_->GetID(), managedType.CString());
+
+                    sourceOut += IndentLine(marshal);
+                }
             }
         }
-    }
-    else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
-    {
-        JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
-
-        if (vtype->vectorType_->asClassType())
+        else if (!function_->IsStatic() && function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
         {
-            String classname = vtype->vectorType_->asClassType()->class_->GetName();
-            String typestring = "Vector<" + classname + ">";
+            JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
 
-            String marshal = "private " + typestring + " ";
+            if (vtype->vectorType_->asClassType())
+            {
+                String classname = vtype->vectorType_->asClassType()->class_->GetName();
+                String typestring = "Vector<" + classname + ">";
 
-            marshal += ToString("%s%s%uReturnValue = new %s();\n", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID(), typestring.CString());
+                String marshal = "private " + typestring + " ";
 
-            sourceOut += IndentLine(marshal);
+                marshal += ToString("%s%s%uReturnValue = new %s();\n", function_->GetClass()->GetName().CString(), function_->GetName().CString(), function_->GetID(), typestring.CString());
 
-        }
+                sourceOut += IndentLine(marshal);
+
+            }
 
+        }
     }
 
     Dedent();

+ 2 - 5
Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp

@@ -143,10 +143,6 @@ void CSModuleWriter::GenerateNativeSource()
 
     source += "\n\nextern \"C\" \n{\n \n";
 
-    source += "// Begin Class Declarations\n";
-
-    source += "// End Class Declarations\n\n";
-
     source += "// Begin Classes\n";
 
     Vector<SharedPtr<JSBClass>> classes = module_->GetClasses();
@@ -214,7 +210,8 @@ String CSModuleWriter::GetManagedPrimitiveType(JSBPrimitiveType* ptype)
 void CSModuleWriter::GenerateManagedClasses(String& source)
 {
 
-    Vector<SharedPtr<JSBClass>> classes = module_->GetClasses();
+    // get All classes and interfaces
+    Vector<SharedPtr<JSBClass>> classes = module_->GetClasses(true);
 
     for (unsigned i = 0; i < classes.Size(); i++)
     {

+ 34 - 0
Source/ToolCore/JSBind/JSBClass.cpp

@@ -275,8 +275,42 @@ void JSBClass::RecursiveAddBaseClass(PODVector<JSBClass*>& baseClasses)
     }
 }
 
+void JSBClass::MergeInterface(JSBClass* interface)
+{
+    if (!interface->IsInterface())
+    {
+        ATOMIC_LOGERRORF("JSBClass::MergeInterface - attempting to merge non-interface class %s", interface->GetName().CString());
+        return;
+    }
+
+    // We merge interfaces via cloning the method for those which aren't implemented in the class itself
+    // We don't use a common native wrapper, as we need to cast (sometimes using multiple inheritance, and this avoids an error prone dynamic cast)
+
+    for (unsigned i = 0; i < interface->functions_.Size(); i++)
+    {
+        JSBFunction* src = interface->functions_[i];
+
+        if (src->Skip() || src->IsConstructor() || src->IsDestructor())
+            continue;
+
+        if (!MatchFunction(src))
+        {
+            JSBFunction* function = src->Clone(this);
+            function->SetInterface(true);
+            AddFunction(function);
+        }
+    }
+}
+
 void JSBClass::Preprocess()
 {
+
+    // merge interfaces
+    for (unsigned i = 0; i < interfaces_.Size(); i++)
+    {
+        MergeInterface(interfaces_[i]);
+    }
+
     RecursiveAddBaseClass(baseClasses_);
 }
 

+ 1 - 0
Source/ToolCore/JSBind/JSBClass.h

@@ -199,6 +199,7 @@ public:
 
 private:
 
+    void MergeInterface(JSBClass* interface);
     void RecursiveAddBaseClass(PODVector<JSBClass *> &baseClasses);
 
     String name_;

+ 28 - 0
Source/ToolCore/JSBind/JSBFunction.cpp

@@ -28,6 +28,7 @@ namespace ToolCore
 unsigned JSBFunction::idCounter_ = 1;
 
 JSBFunction::JSBFunction(JSBClass* klass) : class_(klass), returnType_(0),
+                                  isInterface_(false),
                                   isConstructor_(false), isDestructor_(false),
                                   isGetter_(false), isSetter_(false),
                                   isOverload_(false), skip_(false),
@@ -130,4 +131,31 @@ JSBClass* JSBFunction::GetReturnClass()
 
 }
 
+JSBFunction* JSBFunction::Clone(JSBClass* dstClass)
+{
+    JSBFunction* dst = new JSBFunction(dstClass);
+
+    dst->name_ = name_;
+    dst->propertyName_ = propertyName_;;
+
+    dst->returnType_ = returnType_;
+    dst->parameters_ = parameters_;
+
+    dst->docString_ = docString_;
+
+    dst->isInterface_ = isInterface_;
+    dst->isConstructor_ = isConstructor_;
+    dst->isDestructor_ = isDestructor_;
+    dst->isGetter_ = isGetter_;
+    dst->isSetter_ = isSetter_;
+    dst->isOverload_ = isOverload_;
+    dst->isVirtual_ = isVirtual_;
+    dst->isStatic_ = isStatic_;
+    dst->skip_ = skip_;
+    dst->skipLanguages_ = skipLanguages_;
+
+    return dst;
+}
+
+
 }

+ 8 - 0
Source/ToolCore/JSBind/JSBFunction.h

@@ -143,6 +143,9 @@ public:
 
     bool Match(JSBFunction* func);
 
+    // clones function and adds to specified class
+    JSBFunction* Clone(JSBClass* dstClass);
+
     bool IsConstructor() const { return isConstructor_; }
     bool IsDestructor() const { return isDestructor_; }
     bool IsSetter() const { return isSetter_; }
@@ -150,6 +153,7 @@ public:
     bool IsOverload() { return isOverload_; }
     bool IsVirtual() const { return isVirtual_; }
     bool IsStatic() const { return isStatic_; }
+    bool IsInterface() const { return isInterface_; }
 
     bool Skip(BindingLanguage language = BINDINGLANGUAGE_ANY) const
     {
@@ -173,6 +177,7 @@ public:
     const String& GetDocString() const { return docString_; }
 
     void SetName(const String& name) { name_ = name; }
+    void SetClass(JSBClass* klass) { class_ = klass; }
     void SetConstructor(bool value = true) { isConstructor_ = value; }
     void SetDestructor(bool value = true) { isDestructor_ = value; }
     void SetSetter(bool value = true) { isSetter_ = value; }
@@ -182,6 +187,7 @@ public:
     void SetStatic(bool value = true) { isStatic_ = value; }
     void SetSkip(bool value) { skip_ = value; }
     void SetReturnType(JSBFunctionType* retType) { returnType_ = retType; }
+    void SetInterface(bool interface) { isInterface_ = interface; }
     void SetDocString(const String& docString) { docString_ = docString; }
 
     void SetSkipLanguage(BindingLanguage language, bool skip = true)
@@ -286,6 +292,8 @@ private:
 
     String docString_;
 
+    bool isInterface_;
+
     bool isConstructor_;
     bool isDestructor_;
     bool isGetter_;

+ 0 - 3
Source/ToolCore/JSBind/JSBHeaderVisitor.h

@@ -623,9 +623,6 @@ public:
 
         jclass->SetHeader(header_);
 
-        if (jclass->IsInterface())
-            return true;
-
         String docString = parseDocString(klass->line() - 1);
         if (docString.Length())
             jclass->SetDocString(docString);

+ 6 - 0
Source/ToolCore/NETTools/NETProjectGen.cpp

@@ -419,6 +419,9 @@ namespace ToolCore
         pgroup.CreateChild("ConsolePause").SetValue("false");
         pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
 
+        // Don't warn on missing XML documentation
+        pgroup.CreateChild("NoWarn").SetValue("1591");
+
         if (genAssemblyDocFile_)
         {
             pgroup.CreateChild("DocumentationFile").SetValue(outputPath + assemblyName_ + ".xml");
@@ -509,6 +512,9 @@ namespace ToolCore
         pgroup.CreateChild("ConsolePause").SetValue("false");
         pgroup.CreateChild("AllowUnsafeBlocks").SetValue("true");
 
+        // Don't warn on missing XML documentation
+        pgroup.CreateChild("NoWarn").SetValue("1591");
+
         pgroup.CreateChild("DebugSymbols").SetValue("true");
 
         if (genAssemblyDocFile_)