Exemple #1
0
        void WriteTypeScriptBindingsForProperty(Type declaringType, Property property, CodeWriter code)
        {
            CodeWriter body         = code.Indent();
            string     propertyName = property.Name;

            if (propertyName.StartsWith("Is"))
            {
                propertyName = propertyName.Substring(2);
            }

            bool isInterfaceMember = declaringType is Interface;

            string simpleName = declaringType.Name.Substring(declaringType.Name.IndexOf('+') + 1);

            if (property.GetMethod != null)
            {
                string propertyDeclaration;
                string returnType = this.GetJavaScriptTypeName(property.PropertyType, declaringType);
                if (this.ForceAsyncAPIs)
                {
                    propertyDeclaration =
                        (property.Name.StartsWith("Is") ? Uncapitalize(property.Name) : "get" + property.Name) +
                        "Async";
                    returnType = MakePromiseTypeName(returnType);
                }
                else
                {
                    propertyDeclaration = "get " + Uncapitalize(property.Name);
                }

                code.Code((property.IsStatic ? "static " : String.Empty) +
                          $"{propertyDeclaration}(): {returnType}" + (isInterfaceMember ? ";" : "{"));
                if (!isInterfaceMember)
                {
                    string retCast = "";
                    if (property.PropertyType == "System.Boolean")
                    {
                        retCast = ".then(result => !!result)";
                    }
                    else if (property.PropertyType == "System.Guid")
                    {
                        retCast = ".then(result => (typeof(result) === \"string\" ? " +
                                  "result.toUpperCase() : result && result.value))";
                    }
                    else if (property.PropertyType == "System.Uri")
                    {
                        retCast = ".then(result => (typeof(result) === \"string\" ? " +
                                  "result : result && result.value))";
                    }

                    if (property.IsStatic)
                    {
                        body.Code("return bridge.getStaticProperty(" +
                                  $"{simpleName}.type, \"{propertyName}\"){retCast};");
                    }
                    else
                    {
                        body.Code($"return bridge.getProperty(this, \"{propertyName}\"){retCast};");
                    }

                    code.Code("}");
                }
            }

            if (property.SetMethod != null)
            {
                string propertyDeclaration;
                string returnType;
                string returnStatement;
                if (this.ForceAsyncAPIs)
                {
                    propertyDeclaration = "set" + propertyName + "Async";
                    returnType          = ": " + MakePromiseTypeName("void");
                    returnStatement     = "return ";
                }
                else
                {
                    propertyDeclaration = "set " + Uncapitalize(property.Name);
                    returnType          = String.Empty;
                    returnStatement     = String.Empty;
                }

                string typeName = this.GetJavaScriptTypeName(property.PropertyType, declaringType);
                code.Code((property.IsStatic ? "static " : String.Empty) +
                          $"{propertyDeclaration}(value: {typeName}){returnType}" + (isInterfaceMember ? ";" : "{"));
                if (!isInterfaceMember)
                {
                    string value = "value";
                    if (property.PropertyType == "System.Guid")
                    {
                        value = "(typeof(value) === \"string\" ? { \"type\": \"<uuid>\", \"value\": value } : null)";
                    }
                    else if (property.PropertyType == "System.Uri")
                    {
                        value = "(typeof(value) === \"string\" ? { \"type\": \"<uri>\", \"value\": value } : null)";
                    }

                    if (property.IsStatic)
                    {
                        body.Code($"{returnStatement}bridge.setStaticProperty(" +
                                  $"{simpleName}.type, \"{propertyName}\", {value});");
                    }
                    else
                    {
                        body.Code($"{ returnStatement}bridge.setProperty(this, \"{propertyName}\", {value});");
                    }

                    code.Code("}");
                }
            }
        }
Exemple #2
0
        void WriteTypeScriptBindingForMethod(Type declaringType, Method method, CodeWriter code)
        {
            string methodName = Uncapitalize(method.Name);
            string parameters = String.Join(", ", method.Parameters.Select(
                                                p => p.Name + ": " + this.GetJavaScriptTypeName(p.ParameterType, declaringType)));
            string returnType = this.GetJavaScriptTypeName(method.ReturnType, declaringType);

            if (this.ForceAsyncAPIs)
            {
                returnType = MakePromiseTypeName(returnType);

                if (!methodName.EndsWith("Async"))
                {
                    methodName += "Async";
                }
            }

            bool isInterfaceMethod = (declaringType is Interface);

            code.Code((method.IsStatic ? "static " : String.Empty) +
                      $"{methodName}({parameters}): {returnType}" +
                      (isInterfaceMethod ? ";" : " {"));

            if (!isInterfaceMethod)
            {
                CodeWriter body = code.Indent();

                string retCast = "";
                if (method.ReturnType == "System.Boolean" ||
                    method.ReturnType == "System.Threading.Tasks.Task<System.Boolean>")
                {
                    retCast = ".then(result => !!result)";
                }
                else if (method.ReturnType == "System.Void" ||
                         method.ReturnType == "System.Threading.Tasks.Task")
                {
                    retCast = ".then(result => undefined)";
                }
                else if (method.ReturnType == "System.Guid" ||
                         method.ReturnType == "System.Threading.Tasks.Task<System.Guid>")
                {
                    retCast = ".then(result => (typeof(result) === \"string\" ? " +
                              "result.toUpperCase() : result && result.value))";
                }

                string arguments = String.Join(", ", method.Parameters.Select(p =>
                                                                              p.ParameterType == "System.Guid" ?
                                                                              $"(typeof({p.Name}) === \"string\" ? {{ \"type\": \"<uuid>\", \"value\": {p.Name} }} : null)" :
                                                                              p.ParameterType == "System.Uri" ?
                                                                              $"(typeof({p.Name}) === \"string\" ? {{ \"type\": \"<uri>\", \"value\": {p.Name} }} : null)" :
                                                                              p.Name));
                string implicitContextArgument = GetImplicitContextArgument(method);
                if (implicitContextArgument != null)
                {
                    arguments = (arguments.Length > 0 ? implicitContextArgument + ", " + arguments : implicitContextArgument);
                }

                if (method.IsStatic)
                {
                    string simpleName = declaringType.Name.Substring(declaringType.Name.IndexOf('+') + 1);
                    body.Code("return bridge.invokeStaticMethod(" +
                              $"{simpleName}.type, \"{method.Name}\", [{arguments}]){retCast};");
                }
                else
                {
                    body.Code($"return bridge.invokeMethod(this, \"{method.Name}\", [{arguments}]){retCast};");
                }

                code.Code("}");
            }
        }
Exemple #3
0
        void WriteTypeScriptBindingsForType(
            Type type,
            IEnumerable <Type> importTypes,
            CodeWriter code)
        {
            string simpleTypeName;

            if (!type.IsNested)
            {
                if (!(type is Enum))
                {
                    foreach (Type importType in importTypes)
                    {
                        code.Code($"import {importType.Name} = require(\"./{importType.Name}\");");
                    }

                    if (!(type is Interface))
                    {
                        code.Code();
                        code.Code($"import {{ bridge, NativeObject, NativeReference{(this.ES6 ? "" : ", Promise")} }} " +
                                  $"from \"{this.BridgeModuleName}\";");
                    }
                    else if (!this.ES6)
                    {
                        code.Code();
                        code.Code($"import {{ Promise }} from \"{this.BridgeModuleName}\";");
                    }
                }

                code.Code();

                simpleTypeName = type.Name;
            }
            else
            {
                // TODO: Support multi-level nesting
                simpleTypeName = type.Name.Replace('+', '.');
            }

            simpleTypeName = simpleTypeName.Substring(simpleTypeName.LastIndexOf('.') + 1);

            PluginInfo.AssemblyClassInfo classInfo = this.PluginInfo.Assembly.Classes
                                                     .FirstOrDefault(c => c.Name == type.Name || c.Name == type.FullName);
            bool marshalByValue = (classInfo != null && classInfo.MarshalByValue == "true");

            if (type is Class || type is Struct)
            {
                string extendsTypeName = (marshalByValue ? "NativeObject" : "NativeReference");
                code.Code($"{(type.IsNested ? "export " : "")}class {simpleTypeName} extends {extendsTypeName} {{");
                code.Code($"\tstatic type: string = \"{type.FullName}\";");
            }
            else if (type is Interface)
            {
                code.Code($"{(type.IsNested ? "export " : "")}interface {simpleTypeName} {{");
            }
            else if (type is Enum)
            {
                code.Code($"{(type.IsNested ? "export " : "")}enum {simpleTypeName} {{");
            }
            else
            {
                throw new NotSupportedException("Type type not supported: " + type.GetType().Name);
            }

            CodeWriter            members          = code.Indent();
            Func <Property, bool> isStructProperty = p =>
                                                     p.GetMethod != null && !p.IsStatic;

            if (type is Enum)
            {
                foreach (EnumValue field in type.Members.Cast <EnumValue>().OrderBy(f => (int)f.Value))
                {
                    this.WriteTypeScriptBindingForField(type, field, members);
                }
            }
            else if (marshalByValue)
            {
                // Give the C3P JS marshaller hints about how to convert certain marshal-by-value fields.
                IEnumerable <Property> properties = type.Members.OfType <Property>().Where(isStructProperty);
                string[] guidFields = properties.Where(p => p.PropertyType == "System.Guid")
                                      .Select(p => p.Name).ToArray();
                if (guidFields.Length > 0)
                {
                    members.Code("static typeConversions: any = { " +
                                 String.Join(", ", guidFields.Select(f => $"\"{Uncapitalize(f)}\": \"uuid\"")) + " };");
                }

                bool isFirstField = true;
                foreach (Property property in properties)
                {
                    if (isFirstField)
                    {
                        members.Code();
                        isFirstField = false;
                    }

                    this.WriteTypeScriptBindingForField(type, property, members);
                }
            }

            if (marshalByValue)
            {
                members.Code();
                members.Code(
                    "constructor() {",
                    $"\tsuper({simpleTypeName}.type);",
                    "}");
            }
            else if (type is Class)
            {
                string implicitContextArgument = null;

                foreach (Constructor constructor in type.Members.OfType <Constructor>())
                {
                    members.Code();
                    this.WriteTypeScriptBindingForConstructor(type, constructor, members);

                    if (implicitContextArgument == null)
                    {
                        implicitContextArgument = GetImplicitContextArgument(constructor);
                    }
                }

                string argsWithContext = (implicitContextArgument == null ? "args" :
                                          "[" + implicitContextArgument + "].concat(args)");

                members.Code();
                members.Code("constructor(handle: Promise<number>);");
                members.Code();
                members.Code(
                    $"constructor(...args: any[]) {{",
                    $"\tsuper(",
                    $"\t\t{simpleTypeName}.type,",
                    $"\t\t(args.length === 1 && args[0] instanceof Promise ? args[0] :",
                    $"\t\t\tbridge.createInstance({type.Name}.type, {argsWithContext})));",
                    $"}}");
                members.Code();
                members.Code("dispose(): Promise<void> {");
                members.Code("\tvar releaseNativeInstance: () => Promise<void> = ");
                members.Code("\t\tbridge.releaseInstance.bind(undefined, this.type, this.handle);");
                members.Code("\treturn super.dispose().then(function () { return releaseNativeInstance(); });");
                members.Code("}");
            }

            foreach (Property property in type.Members.OfType <Property>()
                     .Where(p => !marshalByValue || !isStructProperty(p)))
            {
                members.Code();
                this.WriteTypeScriptBindingsForProperty(type, property, members);
            }

            foreach (Event eventMember in type.Members.OfType <Event>())
            {
                members.Code();
                this.WriteTypeScriptBindingForEvent(type, eventMember, members);
            }

            foreach (Method method in type.Members.OfType <Method>())
            {
                members.Code();
                this.WriteTypeScriptBindingForMethod(type, method, members);
            }

            code.Code("}");

            if (!(type is Enum) && !(type is Interface))
            {
                code.Code($"bridge.registerType({simpleTypeName}.type, <any>{simpleTypeName});");
            }

            if (type.Members.OfType <Type>().Count() != 0)
            {
                code.Code();
                code.Code($"module {type.Name} {{");

                foreach (Type nestedType in type.Members.OfType <Type>())
                {
                    code.Code();
                    this.WriteTypeScriptBindingsForType(nestedType, null, code.Indent());
                }

                code.Code("}");
            }

            if (!type.IsNested)
            {
                code.Code();
                code.Code($"export = {type.Name};");
            }
        }