Ejemplo n.º 1
0
        public void DiffBaseibraryV2VsV1()
        {
            AssemblyDiffer         differ = new AssemblyDiffer(TestConstants.BaseLibV1Assembly, TestConstants.BaseLibV2Assembly);
            AssemblyDiffCollection diff   = differ.GenerateTypeDiff(myQueries);

            Assert.AreEqual(4, diff.AddedRemovedTypes.AddedCount, "Added types");
            Assert.AreEqual(4, diff.AddedRemovedTypes.RemovedCount, "Removed types");
            Assert.AreEqual(3, diff.ChangedTypes.Count, "Changed Types");
        }
Ejemplo n.º 2
0
        internal void CreateUsageQueriesFromAssemblyDiff(AssemblyDiffCollection diff)
        {
            List <TypeDefinition> removedTypes = diff.AddedRemovedTypes.RemovedList;

            if (removedTypes.Count > 0)
            {
                // removed types
                new WhoUsesType(myAggregator, removedTypes);
            }

            // changed types
            foreach (TypeDiff changedType in diff.ChangedTypes)
            {
                if (changedType.TypeV1.IsInterface)
                {
                    AddIntefaceChange(changedType);
                }
                else if (changedType.TypeV1.IsEnum)
                {
                    List <FieldDefinition> removedEnumConstants = changedType.Fields.RemovedList;
                    if (removedEnumConstants.Count > 0)
                    {
                        new WhoUsesType(myAggregator, changedType.TypeV1);
                    }
                }
                else
                {
                    List <EventDefinition> removedEvents = changedType.Events.RemovedList;
                    if (removedEvents.Count > 0)
                    {
                        new WhoUsesEvents(myAggregator, removedEvents);
                    }

                    List <MethodDefinition> removedMethods = changedType.Methods.RemovedList;
                    if (removedMethods.Count > 0)
                    {
                        new WhoUsesMethod(myAggregator, removedMethods);
                    }


                    CheckFieldChanges(changedType);

                    if (changedType.Interfaces.RemovedCount > 0)
                    {
                        new WhoUsesType(myAggregator, changedType.TypeV1);
                    }

                    if (changedType.HasChangedBaseType)
                    {
                        new WhoUsesType(myAggregator, changedType.TypeV1);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        internal void Print(AssemblyDiffCollection diff)
        {
            PrintAddedRemovedTypes(diff.AddedRemovedTypes);

            if (diff.ChangedTypes.Count > 0)
            {
                foreach (var typeChange in diff.ChangedTypes)
                {
                    PrintTypeChanges(typeChange);
                }
            }
        }
        public ApiBreakLevel GetBreakLevel(AssemblyDiffCollection diffResult)
        {
            var defaultApiBreakRuleStrategy = new DefaultApiBreakRuleStrategy();

            var apiBreakLevel = defaultApiBreakRuleStrategy.GetBreakLevel(diffResult);

            if (apiBreakLevel == ApiBreakLevel.Major)
            {
                return(ApiBreakLevel.Minor);
            }

            return(apiBreakLevel);
        }
Ejemplo n.º 5
0
        public bool Detect(AssemblyDiffCollection assemblyDiffCollection)
        {
            if (assemblyDiffCollection.AddedRemovedTypes.RemovedCount > 0)
            {
                return(true);
            }

            if (assemblyDiffCollection.ChangedTypes.Count > 0)
            {
                foreach (var typeChange in assemblyDiffCollection.ChangedTypes)
                {
                    if (typeChange.HasChangedBaseType)
                    {
                        return(true);
                    }

                    if (typeChange.Interfaces.Count > 0)
                    {
                        if (typeChange.Interfaces.Removed.Any())
                        {
                            return(true);
                        }
                    }

                    if (typeChange.Events.Removed.Any())
                    {
                        return(true);
                    }

                    if (typeChange.Fields.Removed.Any())
                    {
                        return(true);
                    }

                    if (typeChange.Methods.Removed.Any())
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 6
0
        public override void Execute()
        {
            using (Tracer t = new Tracer(myType, "Execute"))
            {
                base.Execute();
                if (!IsValid)
                {
                    Help();
                    return;
                }

                Out.WriteLine("Compare from {0} against {1}", myParsedArgs.Queries1.GetSearchDirs(), myParsedArgs.Queries2.GetSearchDirs());
                int removedTypes = 0;
                int changedTypes = 0;

                List <string> removedFiles = myParsedArgs.Queries1.GetNotExistingFilesInOtherQuery(myParsedArgs.Queries2);
                if (removedFiles.Count > 0)
                {
                    Out.WriteLine("Removed {0} files", removedFiles.Count);
                    foreach (string str in removedFiles)
                    {
                        Console.WriteLine("\t{0}", Path.GetFileName(str));
                    }
                }

                HashSet <string> query1 = new HashSet <string>(myParsedArgs.Queries1.GetFiles(), new FileNameComparer());
                HashSet <string> query2 = new HashSet <string>(myParsedArgs.Queries2.GetFiles(), new FileNameComparer());

                // Get files which are present in one set and the other
                query1.IntersectWith(query2);
                DiffPrinter printer = new DiffPrinter(Out);

                foreach (string fileName1 in query1)
                {
                    if (fileName1.EndsWith(".XmlSerializers.dll", StringComparison.OrdinalIgnoreCase))
                    {
                        t.Info("Ignore xml serializer dll {0}", fileName1);
                        continue;
                    }

                    string fileName2 = myParsedArgs.Queries2.GetMatchingFileByName(fileName1);

                    var assemblyV1 = AssemblyLoader.LoadCecilAssembly(fileName1);
                    var assemblyV2 = AssemblyLoader.LoadCecilAssembly(fileName2);

                    if (assemblyV1 != null && assemblyV2 != null)
                    {
                        AssemblyDiffer         differ = new AssemblyDiffer(assemblyV1, assemblyV2);
                        AssemblyDiffCollection diff   = differ.GenerateTypeDiff(QueryAggregator.PublicApiQueries);
                        removedTypes += diff.AddedRemovedTypes.RemovedCount;
                        changedTypes += diff.ChangedTypes.Count;

                        if (diff.AddedRemovedTypes.Count > 0 || diff.ChangedTypes.Count > 0)
                        {
                            Out.WriteLine("{0} has {1} changes", Path.GetFileName(fileName1), diff.AddedRemovedTypes.Count +
                                          diff.ChangedTypes.Sum(type => type.Events.Count + type.Fields.Count + type.Interfaces.Count + type.Methods.Count));

                            printer.Print(diff);
                        }
                    }
                }

                Out.WriteLine("From {0} assemblies were {1} types removed and {2} changed.",
                              myParsedArgs.Queries1.GetFiles().Count(), removedTypes, changedTypes);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Marked as internal for unit test purpose. In charge of fetching all the version of an assembly and analyze the public
        /// API to know if there were breaking change or not
        /// </summary>
        internal Tuple <SemanticVersion, string> ResolveConflictingDependancy(IEnumerable <DllReference> conflictingAssembliesVersions, DllReference parentAssembly)
        {
            var         diffs       = new List <AssemblyDiffCollection>();
            DiffPrinter diffPrinter = new DiffPrinter();

            //Skip SemanticVersion until we reach the official SemanticVersion supported
            var asms = conflictingAssembliesVersions.Reverse();

            asms = asms.Reverse();

            //We start to next one as we already set PreviousAPI...
            var previousAPIAssembly = asms.FirstOrDefault();

            asms = asms.Skip(1);
            DllReference selectedVersion = previousAPIAssembly;

            foreach (var apiAssembly in asms)
            {
                diffs = new List <AssemblyDiffCollection>();
                AssemblyDiffCollection diff = null;
                try
                {
                    if (previousAPIAssembly.Path != null && apiAssembly.Path != null)
                    {
                        diff =
                            new AssemblyDiffer(previousAPIAssembly.Path, apiAssembly.Path).GenerateTypeDiff(
                                QueryAggregator.AllExternallyVisibleApis);
                    }
                    //The previous assembly doesn't have any path we can compare with let's forget it
                    else if (previousAPIAssembly.Path == null && apiAssembly.Path != null)
                    {
                        previousAPIAssembly = apiAssembly;
                        continue;
                    }
                    //Current assembly doesn't have any path we can use to compare, ignore it
                    else
                    {
                        continue;
                    }

                    //Nothing Was added between those 2 versions...Strange but let's go ahead
                    if (diff.AddedRemovedTypes.Count <= 0 && diff.ChangedTypes.Count <= 0)
                    {
                        previousAPIAssembly = apiAssembly;
                        continue;
                    }


                    diffs.Add(diff);

                    var aggregator = new UsageQueryAggregator();

                    var breakingChangeSearcher =
                        AppDomain.CurrentDomain.CreateInstanceAndUnwrap(
                            "ApiChange.Api, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
                            "ApiChange.Api.Introspection.Diff.BreakingChangeSearcher", true,
                            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null,
                            new object[] { diffs, aggregator }, null, null);
                    AssemblyDefinition assembly =
                        AssemblyLoader.LoadCecilAssembly(parentAssembly.Path, false);

                    if (assembly != null)
                    {
                        aggregator.Analyze(assembly);
                    }

                    //None of New Types, methods, fields etc. are used in assembly
                    //So we stop here and return the previous one
                    if (aggregator.AssemblyMatches.Count != 0 ||
                        aggregator.TypeMatches.Count != 0 ||
                        aggregator.MethodMatches.Count != 0 ||
                        aggregator.FieldMatches.Count != 0)
                    {
                        selectedVersion = apiAssembly;
                    }
                }
                catch (Exception exc)
                {
                    Trace.TraceError(exc.Message);
                    Trace.TraceError(exc.StackTrace);
                    Trace.TraceError(String.Format("Unable to diff assembly from {0} to {1}", previousAPIAssembly, apiAssembly));
                    //We don't set the prevous assembly because the current raised an exception, let's ignore it totally
                    continue;
                }
                previousAPIAssembly = apiAssembly;
            }
            return(new Tuple <SemanticVersion, string>(selectedVersion.Id.Item1, selectedVersion.Id.Item2));
        }
Ejemplo n.º 8
0
        public override void Execute()
        {
            base.Execute();
            if (!IsValid)
            {
                Help();
                return;
            }

            List <AssemblyDiffCollection> assemblyDiffs = new List <AssemblyDiffCollection>();
            DiffPrinter printer = new DiffPrinter(Out);

            foreach (string newFile in myParsedArgs.NewFiles.GetFiles())
            {
                string oldFile = myParsedArgs.OldFiles.GetMatchingFileByName(newFile);
                if (oldFile == null)
                {
                    oldFile = myParsedArgs.OldFiles2.GetMatchingFileByName(newFile);
                }

                if (oldFile == null)
                {
                    Out.WriteLine("Warning: {0} seems to be a new file. Cannot diff.", Path.GetFileName(newFile));
                    continue;
                }


                try
                {
                    AssemblyDiffer         differ = new AssemblyDiffer(oldFile, newFile);
                    AssemblyDiffCollection diff   = differ.GenerateTypeDiff(QueryAggregator.AllExternallyVisibleApis);
                    if (diff.AddedRemovedTypes.Count > 0 ||
                        diff.ChangedTypes.Count > 0)
                    {
                        Out.WriteLine("Changes of {0}", Path.GetFileName(newFile));
                        printer.Print(diff);
                        assemblyDiffs.Add(diff);
                    }
                }
                catch (ArgumentException)
                {
                    // ignore C++ and other targets in diff
                }
            }

            UsageQueryAggregator usage = new UsageQueryAggregator();

            BreakingChangeSearcher breaking = new BreakingChangeSearcher(assemblyDiffs, usage);

            foreach (string fileV2 in myParsedArgs.SearchInQuery.GetFiles())
            {
                AssemblyDefinition aV2 = AssemblyLoader.LoadCecilAssembly(fileV2);
                if (aV2 != null)
                {
                    usage.Analyze(aV2);
                }
            }

            Out.WriteLine("Detected {0} assemblies which need a recompilation", usage.AssemblyMatches.Count);

            foreach (var needsRecompilation in usage.AssemblyMatches)
            {
                Out.WriteLine("{0}", Path.GetFileName(needsRecompilation));
            }
        }
        public AssemblyDiffCollection Execute(List <FileQuery> oldFiles, List <FileQuery> newFiles)
        {
            using (var t = new Tracer(MyType, "Execute"))
            {
                //var removedTypes = 0;
                //var changedTypes = 0;

                var removedFiles = oldFiles.GetNotExistingFilesInOtherQuery(newFiles);

                if (removedFiles.Count > 0)
                {
                    foreach (var str in removedFiles)
                    {
                        Console.WriteLine("\t{0}", Path.GetFileName(str));
                    }
                }

                var oldFilesQuery = new HashSet <string>(oldFiles.GetFiles(), new FileNameComparer());
                var newFilesQuery = new HashSet <string>(newFiles.GetFiles(), new FileNameComparer());

                // Get files which are present in one set and the other
                oldFilesQuery.IntersectWith(newFilesQuery);
                //DiffPrinter printer = new DiffPrinter(Out);

                var result = new AssemblyDiffCollection();

                foreach (var fileName1 in oldFilesQuery)
                {
                    if (fileName1.EndsWith(".XmlSerializers.dll", StringComparison.OrdinalIgnoreCase))
                    {
                        t.Info("Ignore xml serializer dll {0}", fileName1);
                        continue;
                    }

                    var fileName2 = newFiles.GetMatchingFileByName(fileName1);

                    var assemblyV1 = AssemblyLoader.LoadCecilAssembly(fileName1);
                    var assemblyV2 = AssemblyLoader.LoadCecilAssembly(fileName2);

                    if (assemblyV1 != null && assemblyV2 != null)
                    {
                        var differ      = new AssemblyDiffer(assemblyV1, assemblyV2);
                        var differences = differ.GenerateTypeDiff(QueryAggregator.PublicApiQueries);
                        result.AddedRemovedTypes.AddRange(differences.AddedRemovedTypes);
                        result.ChangedTypes.AddRange(differences.ChangedTypes);

                        //removedTypes += differences.AddedRemovedTypes.RemovedCount;
                        //changedTypes += differences.ChangedTypes.Count;

                        /*if (diff.AddedRemovedTypes.Count > 0 || diff.ChangedTypes.Count > 0)
                         * {
                         *  // Out.WriteLine("{0} has {1} changes", Path.GetFileName(fileName1), diff.AddedRemovedTypes.Count + diff.ChangedTypes.Sum(type => type.Events.Count + type.Fields.Count + type.Interfaces.Count + type.Methods.Count));
                         *
                         *  // printer.Print(diff);
                         *  // Out.WriteLine("From {0} assemblies were {1} types removed and {2} changed.", myParsedArgs.Queries1.GetFiles().Count(), removedTypes, changedTypes);
                         *
                         * }*/
                    }
                }

                return(result);
            }
        }