public void UnsignedMethodsXml()
        {
            // Ensure Kotlin unsigned types end up in the xml
            var klass = LoadClassFile("UnsignedTypes.class");

            KotlinFixups.Fixup(new [] { klass });

            var xml = new XmlClassDeclarationBuilder(klass).ToXElement();

            Assert.AreEqual("uint", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_uint-WZ4Q5Ns").Attribute("return").Value);
            Assert.AreEqual("uint", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_uint-WZ4Q5Ns").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ushort", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ushort-xj2QHRw").Attribute("return").Value);
            Assert.AreEqual("ushort", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ushort-xj2QHRw").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ulong", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ulong-VKZWuLQ").Attribute("return").Value);
            Assert.AreEqual("ulong", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ulong-VKZWuLQ").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ubyte", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ubyte-7apg3OU").Attribute("return").Value);
            Assert.AreEqual("ubyte", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ubyte-7apg3OU").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("uint[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_uintarray--ajY-9A").Attribute("return").Value);
            Assert.AreEqual("uint[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_uintarray--ajY-9A").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ushort[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ushortarray-rL5Bavg").Attribute("return").Value);
            Assert.AreEqual("ushort[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ushortarray-rL5Bavg").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ulong[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ulongarray-QwZRm1k").Attribute("return").Value);
            Assert.AreEqual("ulong[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ulongarray-QwZRm1k").Element("parameter").Attribute("type").Value);

            Assert.AreEqual("ubyte[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ubytearray-GBYM_sE").Attribute("return").Value);
            Assert.AreEqual("ubyte[]", xml.Elements("method").Single(f => f.Attribute("name").Value == "foo_ubytearray-GBYM_sE").Element("parameter").Attribute("type").Value);
        }
        public void HandleKotlinNameShadowing()
        {
            var klass = LoadClassFile("NameShadowing.class");

            KotlinFixups.Fixup(new [] { klass });

            Assert.True(klass.Methods.Single(m => m.Name == "count").AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.True(klass.Methods.Single(m => m.Name == "hitCount").AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.True(klass.Methods.Single(m => m.Name == "setType").AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
        public void HideInternalClass()
        {
            var klass = LoadClassFile("InternalClass.class");

            Assert.True(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));
        }
        public void HideImplementationMethod()
        {
            var klass  = LoadClassFile("MethodImplementation.class");
            var method = klass.Methods.First(m => m.Name == "toString-impl");

            Assert.True(method.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(method.AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
        public void HideInternalConstructor()
        {
            var klass = LoadClassFile("InternalConstructor.class");
            var ctor  = klass.Methods.First(m => m.Name == "<init>");

            Assert.True(ctor.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(ctor.AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
        public void HideInternalMethod()
        {
            var klass  = LoadClassFile("InternalMethod.class");
            var method = klass.Methods.First(m => m.Name == "take$main");

            Assert.True(method.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(method.AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
        public void CreateMethod_EnsureKotlinHashcodeFix()
        {
            var xml   = XDocument.Parse("<package name=\"com.example.test\" jni-name=\"com/example/test\"><class name=\"test\"><method name=\"add-h-_1V8i\" final=\"false\" /></class></package>");
            var klass = XmlApiImporter.CreateClass(xml.Root, xml.Root.Element("class"));

            KotlinFixups.Fixup(new [] { (GenBase)klass }.ToList());

            Assert.AreEqual("Add", klass.Methods [0].Name);
            Assert.IsTrue(klass.Methods [0].IsFinal);
            Assert.IsFalse(klass.Methods [0].IsVirtual);
        }
        public void RenameSetterParameter()
        {
            var klass  = LoadClassFile("SetterParameterName.class");
            var setter = klass.Methods.First(m => m.Name == "setCity");
            var p      = setter.GetParameters() [0];

            Assert.AreEqual("p0", p.Name);

            KotlinFixups.Fixup(new [] { klass });

            Assert.AreEqual("value", p.Name);
        }
        public void ParameterName()
        {
            var klass  = LoadClassFile("ParameterName.class");
            var method = klass.Methods.First(m => m.Name == "take");
            var p      = method.GetParameters() [0];

            Assert.AreEqual("p0", p.Name);

            KotlinFixups.Fixup(new [] { klass });

            Assert.AreEqual("count", p.Name);
        }
        public void RenameExtensionParameter()
        {
            var klass  = LoadClassFile("RenameExtensionParameterKt.class");
            var method = klass.Methods.First(m => m.Name == "toUtf8String");
            var p      = method.GetParameters() [0];

            Assert.AreEqual("$this$toUtf8String", p.Name);

            KotlinFixups.Fixup(new [] { klass });

            Assert.AreEqual("obj", p.Name);
        }
        public void HideInternalProperty()
        {
            var klass  = LoadClassFile("InternalProperty.class");
            var getter = klass.Methods.First(m => m.Name == "getCity$main");
            var setter = klass.Methods.First(m => m.Name == "setCity$main");

            Assert.True(getter.AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.True(setter.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(getter.AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.False(setter.AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
        public void UnsignedFieldsXml()
        {
            // Ensure Kotlin unsigned types end up in the xml
            var klass = LoadClassFile("UnsignedTypesKt.class");

            KotlinFixups.Fixup(new [] { klass });

            var xml = new XmlClassDeclarationBuilder(klass).ToXElement();

            Assert.AreEqual("uint", xml.Elements("field").Single(f => f.Attribute("name").Value == "UINT_CONST").Attribute("type").Value);
            Assert.AreEqual("ushort", xml.Elements("field").Single(f => f.Attribute("name").Value == "USHORT_CONST").Attribute("type").Value);
            Assert.AreEqual("ulong", xml.Elements("field").Single(f => f.Attribute("name").Value == "ULONG_CONST").Attribute("type").Value);
            Assert.AreEqual("ubyte", xml.Elements("field").Single(f => f.Attribute("name").Value == "UBYTE_CONST").Attribute("type").Value);
        }
Exemple #13
0
        public void HideInternalConstructor()
        {
            var klass = LoadClassFile("InternalConstructor.class");
            var ctor  = klass.Methods.First(m => m.Name == "<init>");

            Assert.True(ctor.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(ctor.AccessFlags.HasFlag(MethodAccessFlags.Public));

            var output = new XmlClassDeclarationBuilder(klass).ToXElement().ToString();

            Assert.True(output.Contains("visibility=\"kotlin-internal\""));
        }
        public void UnsignedFields()
        {
            var klass = LoadClassFile("UnsignedTypesKt.class");

            var uint_field   = klass.Fields.Single(m => m.Name == "UINT_CONST");
            var ushort_field = klass.Fields.Single(m => m.Name == "USHORT_CONST");
            var ulong_field  = klass.Fields.Single(m => m.Name == "ULONG_CONST");
            var ubyte_field  = klass.Fields.Single(m => m.Name == "UBYTE_CONST");

            KotlinFixups.Fixup(new [] { klass });

            Assert.AreEqual("uint", uint_field.KotlinType);
            Assert.AreEqual("ushort", ushort_field.KotlinType);
            Assert.AreEqual("ulong", ulong_field.KotlinType);
            Assert.AreEqual("ubyte", ubyte_field.KotlinType);
        }
        public void UnsignedMethods()
        {
            var klass = LoadClassFile("UnsignedTypes.class");

            var uint_method           = klass.Methods.Single(m => m.Name.Contains("foo_uint-"));
            var ushort_method         = klass.Methods.Single(m => m.Name.Contains("foo_ushort-"));
            var ulong_method          = klass.Methods.Single(m => m.Name.Contains("foo_ulong-"));
            var ubyte_method          = klass.Methods.Single(m => m.Name.Contains("foo_ubyte-"));
            var uintarray_method      = klass.Methods.Single(m => m.Name.Contains("foo_uintarray-"));
            var ushortarray_method    = klass.Methods.Single(m => m.Name.Contains("foo_ushortarray-"));
            var ulongarray_method     = klass.Methods.Single(m => m.Name.Contains("foo_ulongarray-"));
            var ubytearray_method     = klass.Methods.Single(m => m.Name.Contains("foo_ubytearray-"));
            var uintarrayarray_method = klass.Methods.Single(m => m.Name.Contains("foo_uintarrayarray"));

            KotlinFixups.Fixup(new [] { klass });

            Assert.AreEqual("uint", uint_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("uint", uint_method.KotlinReturnType);

            Assert.AreEqual("ushort", ushort_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ushort", ushort_method.KotlinReturnType);

            Assert.AreEqual("ulong", ulong_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ulong", ulong_method.KotlinReturnType);

            Assert.AreEqual("ubyte", ubyte_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ubyte", ubyte_method.KotlinReturnType);

            Assert.AreEqual("uint[]", uintarray_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("uint[]", uintarray_method.KotlinReturnType);

            Assert.AreEqual("ushort[]", ushortarray_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ushort[]", ushortarray_method.KotlinReturnType);

            Assert.AreEqual("ulong[]", ulongarray_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ulong[]", ulongarray_method.KotlinReturnType);

            Assert.AreEqual("ubyte[]", ubytearray_method.GetParameters() [0].KotlinType);
            Assert.AreEqual("ubyte[]", ubytearray_method.KotlinReturnType);

            // Kotlin's Array<UIntArray> does not trigger this code because it is not
            // encoded as Java's "[[I", instead it is exposed as "UIntArray[]", so
            // we treat it as a normal class array.
            Assert.Null(uintarrayarray_method.GetParameters() [0].KotlinType);
            Assert.Null(uintarrayarray_method.KotlinReturnType);
        }
Exemple #16
0
        public void HideInternalClass()
        {
            var klass       = LoadClassFile("InternalClass.class");
            var inner_class = klass.InnerClasses.First();

            Assert.True(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));
            Assert.True(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));
            Assert.False(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Public));

            var output = new XmlClassDeclarationBuilder(klass).ToXElement().ToString();

            Assert.True(output.Contains("visibility=\"private\""));
        }
Exemple #17
0
        public void HideInternalProperty()
        {
            var klass  = LoadClassFile("InternalProperty.class");
            var getter = klass.Methods.First(m => m.Name == "getCity$main");
            var setter = klass.Methods.First(m => m.Name == "setCity$main");

            Assert.True(getter.AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.True(setter.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            Assert.False(getter.AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.False(setter.AccessFlags.HasFlag(MethodAccessFlags.Public));

            var output = new XmlClassDeclarationBuilder(klass).ToXElement().ToString();

            Assert.True(output.Contains("visibility=\"kotlin-internal\""));
        }
        public void MakeInternalInterfacePackagePrivate()
        {
            var klass       = LoadClassFile("InternalInterface.class");
            var inner_class = klass.InnerClasses.First();

            Assert.True(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));
            Assert.True(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            // "package-private" is denoted as no visibility flags
            Assert.False(klass.AccessFlags.HasFlag(ClassAccessFlags.Public));
            Assert.False(klass.AccessFlags.HasFlag(ClassAccessFlags.Protected));
            Assert.False(klass.AccessFlags.HasFlag(ClassAccessFlags.Private));

            Assert.False(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Public));
            Assert.False(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Protected));
            Assert.False(inner_class.InnerClassAccessFlags.HasFlag(ClassAccessFlags.Private));
        }
        public void HideDefaultConstructorMarker()
        {
            var klass = LoadClassFile("DefaultConstructor.class");

            // init ()
            var ctor_0p = klass.Methods.Single(m => m.Name == "<init>" && m.GetParameters().Length == 0);

            // init (string name)
            var ctor_1p = klass.Methods.Single(m => m.Name == "<init>" && m.GetParameters().Length == 1);

            // init (string p0, int p1, DefaultConstructorMarker p2)
            var ctor_3p = klass.Methods.Single(m => m.Name == "<init>" && m.GetParameters().Length == 3);

            Assert.True(ctor_3p.AccessFlags.HasFlag(MethodAccessFlags.Public));

            KotlinFixups.Fixup(new [] { klass });

            // Assert that the normal constructors are still public
            Assert.True(ctor_0p.AccessFlags.HasFlag(MethodAccessFlags.Public));
            Assert.True(ctor_1p.AccessFlags.HasFlag(MethodAccessFlags.Public));

            // Assert that the synthetic "DefaultConstructorMarker" constructor has been marked private
            Assert.False(ctor_3p.AccessFlags.HasFlag(MethodAccessFlags.Public));
        }
Exemple #20
0
        static void Run(CodeGeneratorOptions options, DirectoryAssemblyResolver resolver)
        {
            string assemblyQN              = options.AssemblyQualifiedName;
            string api_level               = options.ApiLevel;
            int    product_version         = options.ProductVersion;
            bool   preserve_enums          = options.PreserveEnums;
            string csdir                   = options.ManagedCallableWrapperSourceOutputDirectory ?? "cs";
            string javadir                 = "java";
            string enumdir                 = options.EnumOutputDirectory ?? "enum";
            string enum_metadata           = options.EnumMetadataOutputFile ?? "enummetadata";
            var    references              = options.AssemblyReferences;
            string enum_fields_map         = options.EnumFieldsMapFile;
            string enum_flags              = options.EnumFlagsFile;
            string enum_methods_map        = options.EnumMethodsMapFile;
            var    fixups                  = options.FixupFiles;
            var    annotations_zips        = options.AnnotationsZipFiles;
            string filename                = options.ApiDescriptionFile;
            string mapping_file            = options.MappingReportFile;
            bool   only_xml_adjuster       = options.OnlyRunApiXmlAdjuster;
            string api_xml_adjuster_output = options.ApiXmlAdjusterOutput;
            var    apiSource               = "";
            var    opt = new CodeGenerationOptions()
            {
                CodeGenerationTarget           = options.CodeGenerationTarget,
                UseGlobal                      = options.GlobalTypeNames,
                IgnoreNonPublicType            = true,
                UseShortFileNames              = options.UseShortFileNames,
                ProductVersion                 = options.ProductVersion,
                SupportInterfaceConstants      = options.SupportInterfaceConstants,
                SupportDefaultInterfaceMethods = options.SupportDefaultInterfaceMethods,
                SupportNestedInterfaceTypes    = options.SupportNestedInterfaceTypes,
                SupportNullableReferenceTypes  = options.SupportNullableReferenceTypes,
            };
            var resolverCache = new TypeDefinitionCache();

            // Load reference libraries

            foreach (var lib in options.LibraryPaths)
            {
                resolver.SearchDirectories.Add(lib);
            }
            foreach (var reference in references)
            {
                resolver.SearchDirectories.Add(Path.GetDirectoryName(reference));
            }

            // Figure out if this is class-parse
            string apiXmlFile    = filename;
            string apiSourceAttr = null;

            using (var xr = XmlReader.Create(filename)) {
                xr.MoveToContent();
                apiSourceAttr = xr.GetAttribute("api-source");
            }

            // We don't use shallow referenced types with class-parse because the Adjuster process
            // enumerates every ctor/method/property/field to build its model, so we will need
            // every type to be fully populated.
            opt.UseShallowReferencedTypes = apiSourceAttr != "class-parse";

            foreach (var reference in references.Distinct())
            {
                try {
                    Report.Verbose(0, "resolving assembly {0}.", reference);
                    var assembly = resolver.Load(reference);
                    foreach (var md in assembly.Modules)
                    {
                        foreach (var td in md.Types)
                        {
                            // FIXME: at some stage we want to import generic types.
                            // For now generator fails to load generic types that have conflicting type e.g.
                            // AdapterView`1 and AdapterView cannot co-exist.
                            // It is mostly because generator primarily targets jar (no real generics land).
                            var nonGenericOverload = td.HasGenericParameters
                                                                ? md.GetType(td.FullName.Substring(0, td.FullName.IndexOf('`')))
                                                                : null;
                            if (BindSameType(td, nonGenericOverload, resolverCache))
                            {
                                continue;
                            }
                            ProcessReferencedType(td, opt);
                        }
                    }
                } catch (Exception ex) {
                    Report.Warning(0, Report.WarningCodeGenerator + 0, ex, "failed to parse assembly {0}: {1}", reference, ex.Message);
                }
            }

            // For class-parse API description, transform it to jar2xml style.
            if (apiSourceAttr == "class-parse")
            {
                apiXmlFile = api_xml_adjuster_output ?? Path.Combine(Path.GetDirectoryName(filename), Path.GetFileName(filename) + ".adjusted");
                new Adjuster().Process(filename, opt, opt.SymbolTable.AllRegisteredSymbols(opt).OfType <GenBase> ().ToArray(), apiXmlFile, Report.Verbosity ?? 0);
            }
            if (only_xml_adjuster)
            {
                return;
            }

            // load XML API definition with fixups.

            Dictionary <string, EnumMappings.EnumDescription> enums = null;

            EnumMappings enummap = null;

            if (enum_fields_map != null || enum_methods_map != null)
            {
                enummap = new EnumMappings(enumdir, enum_metadata, api_level, preserve_enums);
                enums   = enummap.Process(enum_fields_map, enum_flags, enum_methods_map);
                fixups.Add(enum_metadata);
            }

            Parser         p    = new Parser(opt);
            List <GenBase> gens = p.Parse(apiXmlFile, fixups, api_level, product_version);

            if (gens == null)
            {
                return;
            }
            apiSource = p.ApiSource;

            // disable interface default methods here, especially before validation.
            gens = gens.Where(g => !g.IsObfuscated && g.Visibility != "private").ToList();
            foreach (var gen in gens)
            {
                gen.StripNonBindables(opt);
                if (gen.IsGeneratable)
                {
                    AddTypeToTable(opt, gen);
                }
            }

            // Apply fixups
            KotlinFixups.Fixup(gens);

            Validate(gens, opt, new CodeGeneratorContext());

            foreach (var api_versions_xml in options.ApiVersionsXmlFiles)
            {
                ApiVersionsSupport.AssignApiLevels(gens, api_versions_xml);
            }

            foreach (GenBase gen in gens)
            {
                gen.FillProperties();
            }

            var cache = new AncestorDescendantCache(gens);

            foreach (var gen in gens)
            {
                gen.UpdateEnums(opt, cache);
            }

            foreach (GenBase gen in gens)
            {
                gen.FixupMethodOverrides(opt);
            }

            foreach (GenBase gen in gens)
            {
                gen.FixupExplicitImplementation();
            }

            SealedProtectedFixups.Fixup(gens);

            GenerateAnnotationAttributes(gens, annotations_zips);

            //SymbolTable.Dump ();

            GenerationInfo gen_info = new GenerationInfo(csdir, javadir, assemblyQN);

            opt.AssemblyName = gen_info.Assembly;

            if (mapping_file != null)
            {
                GenerateMappingReportFile(gens, mapping_file);
            }

            foreach (IGeneratable gen in gens)
            {
                if (gen.IsGeneratable)
                {
                    gen.Generate(opt, gen_info);
                }
            }

            new NamespaceMapping(gens).Generate(opt, gen_info);


            ClassGen.GenerateTypeRegistrations(opt, gen_info);
            ClassGen.GenerateEnumList(gen_info);

            // Create the .cs files for the enums
            var enumFiles = enums == null
                                ? null
                                : enummap.WriteEnumerations(enumdir, enums, FlattenNestedTypes(gens).ToArray(), opt.UseShortFileNames);

            gen_info.GenerateLibraryProjectFile(options, enumFiles);
        }