예제 #1
0
        public void FixAbstractMethodsStep_SkipDimMembers()
        {
            var path     = Path.Combine(Path.GetFullPath(XABuildPaths.TestOutputDirectory), "temp", TestName);
            var step     = new FixAbstractMethodsStep();
            var pipeline = new Pipeline();

            Directory.CreateDirectory(path);

            using (var context = new LinkContext(pipeline)) {
                context.Resolver.AddSearchDirectory(path);

                var myAssemblyPath = Path.Combine(path, "MyAssembly.dll");

                using (var android = CreateFauxMonoAndroidAssembly()) {
                    android.Write(Path.Combine(path, "Mono.Android.dll"));
                    CreateAbstractIfaceImplementation(myAssemblyPath, android);
                }

                using (var assm = context.Resolve(myAssemblyPath)) {
                    step.Process(context);

                    var impl = assm.MainModule.GetType("MyNamespace.MyClass");

                    Assert.IsTrue(impl.Methods.Any(m => m.Name == "MyAbstractMethod"), "We should have generated an override for MyAbstractMethod");
                    Assert.IsFalse(impl.Methods.Any(m => m.Name == "MyDefaultMethod"), "We should not have generated an override for MyDefaultMethod");
                }
            }

            Directory.Delete(path, true);
        }
예제 #2
0
        public void FixAbstractMethodsStep_Explicit()
        {
            var path     = Path.Combine(Path.GetFullPath(XABuildPaths.TestOutputDirectory), "temp", TestName);
            var step     = new FixAbstractMethodsStep(new TypeDefinitionCache());
            var pipeline = new Pipeline();

            Directory.CreateDirectory(path);

            using (var context = new LinkContext(pipeline)) {
                context.Resolver.AddSearchDirectory(path);

                var myAssemblyPath = Path.Combine(path, "MyAssembly.dll");

                using (var android = CreateFauxMonoAndroidAssembly()) {
                    android.Write(Path.Combine(path, "Mono.Android.dll"));
                    CreateExplicitInterface(myAssemblyPath, android);
                }

                using (var assm = context.Resolve(myAssemblyPath)) {
                    step.Process(context);

                    var impl = assm.MainModule.GetType("MyNamespace.MyClass");
                    Assert.AreEqual(2, impl.Methods.Count, "MyClass should contain 2 methods");
                    var method = impl.Methods.FirstOrDefault(m => m.Name == "MyNamespace.IMyInterface.MyMethod");
                    Assert.IsNotNull(method, "MyNamespace.IMyInterface.MyMethod should exist");
                    method = impl.Methods.FirstOrDefault(m => m.Name == "MyMissingMethod");
                    Assert.IsNotNull(method, "MyMissingMethod should exist");
                }
            }

            Directory.Delete(path, true);
        }
예제 #3
0
        public void FixAbstractMethodsStep_SkipDimMembers()
        {
            var step     = new FixAbstractMethodsStep();
            var pipeline = new Pipeline();
            var context  = new LinkContext(pipeline);

            var android = CreateFauxMonoAndroidAssembly();
            var jlo     = android.MainModule.GetType("Java.Lang.Object");

            context.Resolver.CacheAssembly(android);

            var assm      = AssemblyDefinition.CreateAssembly(new AssemblyNameDefinition("DimTest", new Version()), "DimTest", ModuleKind.Dll);
            var void_type = assm.MainModule.ImportReference(typeof(void));

            // Create interface
            var iface = new TypeDefinition("MyNamespace", "IMyInterface", TypeAttributes.Interface);

            var abstract_method = new MethodDefinition("MyAbstractMethod", MethodAttributes.Abstract, void_type);
            var default_method  = new MethodDefinition("MyDefaultMethod", MethodAttributes.Public, void_type);

            iface.Methods.Add(abstract_method);
            iface.Methods.Add(default_method);

            assm.MainModule.Types.Add(iface);

            // Create implementing class
            var impl = new TypeDefinition("MyNamespace", "MyClass", TypeAttributes.Public, jlo);

            impl.Interfaces.Add(new InterfaceImplementation(iface));

            assm.MainModule.Types.Add(impl);

            context.Resolver.CacheAssembly(assm);

            step.Process(context);

            // We should have generated an override for MyAbstractMethod
            Assert.IsTrue(impl.Methods.Any(m => m.Name == "MyAbstractMethod"));

            // We should not have generated an override for MyDefaultMethod
            Assert.IsFalse(impl.Methods.Any(m => m.Name == "MyDefaultMethod"));
        }
예제 #4
0
        public override bool RunTask()
        {
            if (SourceFiles.Length != DestinationFiles.Length)
            {
                throw new ArgumentException("source and destination count mismatch");
            }

            var readerParameters = new ReaderParameters {
                ReadSymbols = true,
            };
            var writerParameters = new WriterParameters {
                DeterministicMvid = Deterministic,
            };

            using (var resolver = new DirectoryAssemblyResolver(this.CreateTaskLogger(), loadDebugSymbols: true, loadReaderParameters: readerParameters)) {
                // Add SearchDirectories with ResolvedAssemblies
                foreach (var assembly in ResolvedAssemblies)
                {
                    var path = Path.GetFullPath(Path.GetDirectoryName(assembly.ItemSpec));
                    if (!resolver.SearchDirectories.Contains(path))
                    {
                        resolver.SearchDirectories.Add(path);
                    }
                }

                // Run the FixAbstractMethodsStep
                var step = new FixAbstractMethodsStep(resolver, Log);
                for (int i = 0; i < SourceFiles.Length; i++)
                {
                    var source      = SourceFiles [i];
                    var destination = DestinationFiles [i];

                    // Only run the step on "MonoAndroid" assemblies
                    if (MonoAndroidHelper.IsMonoAndroidAssembly(source) && !MonoAndroidHelper.IsSharedRuntimeAssembly(source.ItemSpec))
                    {
                        var assemblyDefinition = resolver.GetAssembly(source.ItemSpec);
                        if (step.FixAbstractMethods(assemblyDefinition))
                        {
                            Log.LogDebugMessage($"Saving modified assembly: {destination.ItemSpec}");
                            writerParameters.WriteSymbols = assemblyDefinition.MainModule.HasSymbols;
                            assemblyDefinition.Write(destination.ItemSpec, writerParameters);
                            continue;
                        }
                    }

                    if (MonoAndroidHelper.CopyAssemblyAndSymbols(source.ItemSpec, destination.ItemSpec))
                    {
                        Log.LogDebugMessage($"Copied: {destination.ItemSpec}");
                    }
                    else
                    {
                        Log.LogDebugMessage($"Skipped unchanged file: {destination.ItemSpec}");

                        // NOTE: We still need to update the timestamp on this file, or this target would run again
                        File.SetLastWriteTimeUtc(destination.ItemSpec, DateTime.UtcNow);
                    }
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool RunTask()
        {
            if (SourceFiles.Length != DestinationFiles.Length)
            {
                throw new ArgumentException("source and destination count mismatch");
            }

            var readerParameters = new ReaderParameters {
                ReadSymbols = true,
            };
            var writerParameters = new WriterParameters {
                DeterministicMvid = Deterministic,
            };

            using (var resolver = new DirectoryAssemblyResolver(this.CreateTaskLogger(), loadDebugSymbols: true, loadReaderParameters: readerParameters)) {
                // Add SearchDirectories with ResolvedAssemblies
                foreach (var assembly in ResolvedAssemblies)
                {
                    var path = Path.GetFullPath(Path.GetDirectoryName(assembly.ItemSpec));
                    if (!resolver.SearchDirectories.Contains(path))
                    {
                        resolver.SearchDirectories.Add(path);
                    }
                }

                // Set up the FixAbstractMethodsStep
                var step1 = new FixAbstractMethodsStep(resolver, new TypeDefinitionCache(), Log);
                // Set up the AddKeepAlivesStep
                var step2 = new MonoDroid.Tuner.AddKeepAlivesStep(new TypeDefinitionCache());
                for (int i = 0; i < SourceFiles.Length; i++)
                {
                    var source      = SourceFiles [i];
                    var destination = DestinationFiles [i];
                    AssemblyDefinition assemblyDefinition = null;

                    var assemblyName = Path.GetFileNameWithoutExtension(source.ItemSpec);
                    if (!MTProfile.IsSdkAssembly(assemblyName) && !MTProfile.IsProductAssembly(assemblyName))
                    {
                        assemblyDefinition = resolver.GetAssembly(source.ItemSpec);
                        step1.CheckAppDomainUsage(assemblyDefinition, (string msg) => Log.LogMessageFromText(msg, MessageImportance.High));
                    }

                    // Only run the step on "MonoAndroid" assemblies
                    if (MonoAndroidHelper.IsMonoAndroidAssembly(source) && !MonoAndroidHelper.IsSharedRuntimeAssembly(source.ItemSpec))
                    {
                        if (assemblyDefinition == null)
                        {
                            assemblyDefinition = resolver.GetAssembly(source.ItemSpec);
                        }

                        if (step1.FixAbstractMethods(assemblyDefinition) ||
                            (AddKeepAlives && step2.AddKeepAlives(assemblyDefinition)))
                        {
                            Log.LogDebugMessage($"Saving modified assembly: {destination.ItemSpec}");
                            writerParameters.WriteSymbols = assemblyDefinition.MainModule.HasSymbols;
                            assemblyDefinition.Write(destination.ItemSpec, writerParameters);
                            continue;
                        }
                    }

                    if (MonoAndroidHelper.CopyAssemblyAndSymbols(source.ItemSpec, destination.ItemSpec))
                    {
                        Log.LogDebugMessage($"Copied: {destination.ItemSpec}");
                    }
                    else
                    {
                        Log.LogDebugMessage($"Skipped unchanged file: {destination.ItemSpec}");

                        // NOTE: We still need to update the timestamp on this file, or this target would run again
                        File.SetLastWriteTimeUtc(destination.ItemSpec, DateTime.UtcNow);
                    }
                }
            }

            return(!Log.HasLoggedErrors);
        }