public void Can_Find_IDisposable_Implementer_Without_Pdb()
        {
            var iDisposable = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IDisposable");

            UsageQueryAggregator agg = new UsageQueryAggregator();

            new WhoImplementsInterface(agg, iDisposable);

            try
            {
                agg.Analyze(TestConstants.DependandLibV1Assembly);
                var results = agg.TypeMatches;
                Assert.AreEqual(2, results.Count);
            }
            finally
            {
                if (ExceptionHelper.InException)
                {
                    foreach (var typeMatch in agg.TypeMatches)
                    {
                        Console.WriteLine("IDisposable is implemeted by {0}: {1}", typeMatch.Match.Print(), typeMatch.SourceFileName);
                    }
                }
            }
        }
Beispiel #2
0
        public void Throw_When_Empty_Stirng_IsPassed()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator();

            agg.AddVisitScope("test");
            Assert.Throws <ArgumentException>(() => new WhoUsesStringConstant(agg, ""));
        }
        public void Can_Find_Field_Where_Type_Is_A_Generic_Parameter()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(
                new TypeQuery("BaseLibrary.FieldQuery", "PublicClassWithManyEventsAndMethods"));


            TypeDefinition decimalType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Decimal");

            new WhoHasFieldOfType(agg, decimalType);

            try
            {
                agg.Analyze(TestConstants.BaseLibV1Assembly);

                Assert.AreEqual(1, agg.FieldMatches.Count, "Field match count");
                Assert.AreEqual("myDecimalField", agg.FieldMatches[0].Match.Name, "Field Name");
            }
            finally
            {
                if (ExceptionHelper.InException)
                {
                    foreach (var res in agg.FieldMatches)
                    {
                        Console.WriteLine("Found field: {0}, file: {1}", res.Match.Print(FieldPrintOptions.All), res.SourceFileName);
                    }
                }
            }
        }
Beispiel #4
0
        public override void Execute()
        {
            base.Execute();
            if (!IsValid)
            {
                Help();
                return;
            }

            int assemblyRefCount = 0;

            Out.WriteLine("The following assemblies reference {0}", Path.GetFileName(myReferencedAssembly));
            LoadAssemblies(myParsedArgs.Queries2, (cecilAssembly, file) =>
            {
                using (UsageQueryAggregator aggregator = new UsageQueryAggregator())
                {
                    new WhoReferencesAssembly(aggregator, myReferencedAssembly);

                    aggregator.Analyze(cecilAssembly);
                    if (aggregator.AssemblyMatches.Count > 0)
                    {
                        Out.WriteLine("{0}", aggregator.AssemblyMatches.ToList()[0]);
                    }

                    lock (this)
                    {
                        assemblyRefCount += aggregator.AssemblyMatches.Count;
                    }
                }
            });

            Out.WriteLine("Total References: {0}", assemblyRefCount);
        }
Beispiel #5
0
        public void Can_Differentiate_Methods_With_GenericParameters()
        {
            TypeDefinition baseClassMethod = TypeQuery.GetTypeByName(TestConstants.BaseLibV1Assembly, "BaseLibrary.ApiChanges.PublicBaseClass");
            var            baseMethods     = new MethodQuery("public void DoSomeThing(System.Collections.Generic.List<int> l)").GetMethods(baseClassMethod);

            Assert.AreEqual(1, baseMethods.Count, "Should get only one method with generic parameter");

            UsageQueryAggregator agg = new UsageQueryAggregator();

            new WhoUsesMethod(agg, baseMethods);

            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "Method match count");
            HashSet <string> methods = new HashSet <string>(from m in agg.MethodMatches
                                                            select m.Match.Print(MethodPrintOption.Full));

            Assert.IsTrue(methods.Contains("public void CallGenericIntFunc(PublicBaseClass cl)"));

            var methodWithFloatAsGenericParam = new MethodQuery("public void DoSomeThing(System.Collections.Generic.List<float> l)").GetMethods(baseClassMethod);

            Assert.AreEqual(1, methodWithFloatAsGenericParam.Count, "Did not find long function");

            agg.Dispose();

            agg = new UsageQueryAggregator();
            new WhoUsesMethod(agg, methodWithFloatAsGenericParam);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.MethodMatches.Count, "Method match count");
            Assert.AreEqual("public void CallGenericFloatFunc(PublicBaseClass cl)", agg.MethodMatches[0].Match.Print(MethodPrintOption.Full));
        }
Beispiel #6
0
        public void Validate_That_Simple_Method_Calls_From_Local_Variable_Is_Found()
        {
            TypeDefinition baseClassMethod = TypeQuery.GetTypeByName(TestConstants.BaseLibV1Assembly, "BaseLibrary.ApiChanges.PublicBaseClass");
            var            baseMethods     = MethodQuery.AllMethods.GetMethods(baseClassMethod);

            UsageQueryAggregator agg = new UsageQueryAggregator();

            new WhoUsesMethod(agg, baseMethods);

            try
            {
                agg.Analyze(TestConstants.DependandLibV1Assembly);
                var results = agg.MethodMatches;
                Assert.AreEqual(8, results.Count);
            }
            finally
            {
                if (ExceptionHelper.InException)
                {
                    foreach (var res in agg.MethodMatches)
                    {
                        Console.WriteLine("Got method call at {0} {1} {2}", res.Match.Print(MethodPrintOption.Full),
                                          res.SourceFileName, res.LineNumber);
                    }
                }

                agg.Dispose();
            }
        }
        public void Can_Find_Non_Compilergenerated_Generic_Field()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(
                new TypeQuery("BaseLibrary.FieldQuery", "PublicClassWithManyEventsAndMethods"));


            TypeDefinition func = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Collections.Generic.KeyValuePair`2");

            new WhoHasFieldOfType(agg, func);

            try
            {
                agg.Analyze(TestConstants.BaseLibV1Assembly);

                Assert.AreEqual(1, agg.FieldMatches.Count, "Field match count");
                Assert.AreEqual("ProtectedKeyValuePairField", agg.FieldMatches[0].Match.Name, "Field Name");
            }
            finally
            {
                if (ExceptionHelper.InException)
                {
                    foreach (var res in agg.FieldMatches)
                    {
                        Console.WriteLine("Found field: {0}, file: {1}", res.Match.Print(FieldPrintOptions.All), res.SourceFileName);
                    }
                }
            }
        }
Beispiel #8
0
        public void Can_Find_Reference_Type_Instantiations()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoInstantiatesQueries", "ClassWhichInstantiatesReferenceType"));

            new WhoInstantiatesType(agg, TypeQuery.GetTypeByName(TestConstants.BaseLibV1Assembly, "BaseLibrary.ApiChanges.PublicGenericClass`1"));
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.MethodMatches.Count, "Should get ctor call");
        }
Beispiel #9
0
        public void Can_Find_Word_Case_InsenstiveSensitive()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator();

            agg.AddVisitScope(TestConstants.BaseLibV1);
            new WhoUsesStringConstant(agg, "GLOBAL A STRING", true, StringComparison.OrdinalIgnoreCase);
            agg.Analyze(TestConstants.DependandLibV1Assembly);
            Assert.AreEqual(2, agg.MethodMatches.Count);
        }
Beispiel #10
0
        public void Cannot_Find_Word_If_Casing_Is_Different()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator();

            agg.AddVisitScope(TestConstants.BaseLibV1);
            new WhoUsesStringConstant(agg, "GLOBAL A STRING", true, StringComparison.Ordinal);
            agg.Analyze(TestConstants.DependandLibV1Assembly);
            Assert.AreEqual(0, agg.MethodMatches.Count);
        }
Beispiel #11
0
        public void Can_Find_Value_Type_Instantiations()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoInstantiatesQueries", "ClassWhichInstantiatesValueType"));

            new WhoInstantiatesType(agg, TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.DateTime"));
            new WhoInstantiatesType(agg, TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Threading.AsyncFlowControl"));
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(3, agg.MethodMatches.Count, "Should get ctor call");
        }
Beispiel #12
0
        public void Can_Detect_Enum_Usage_In_Switch_Case()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("BaseLibrary.TypeUsageQuery", "SwitchOfEnumValues"));

            new WhoUsesType(agg, TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.StringSplitOptions"));
            agg.Analyze(TestConstants.BaseLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "method match count");
            Assert.AreEqual("UsingSwitchWithEnum", agg.MethodMatches[0].Match.Name);
        }
Beispiel #13
0
        public void Can_Find_Substring()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator();

            agg.AddVisitScope(TestConstants.BaseLibV1);
            new WhoUsesStringConstant(agg, "Global A");
            agg.Analyze(TestConstants.DependandLibV1Assembly);
            Assert.AreEqual(3, agg.MethodMatches.Count);
            Assert.AreEqual(1, agg.FieldMatches.Count);
        }
Beispiel #14
0
        public void Can_Find_TypeOfAndCast_Calls()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "CastToTypeAndTypeof"));

            new WhoUsesType(agg, TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IDisposable"));
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "Method match count");
            Assert.AreEqual(WhoUsesType.CastReason, agg.MethodMatches[0].Annotations.Reason);
            Assert.AreEqual(WhoUsesType.TypeOfReason, agg.MethodMatches[1].Annotations.Reason);
        }
Beispiel #15
0
        public void Can_Detect_Type_Usage_In_Interface()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("BaseLibrary.TypeUsageQuery", "ITestInterface"));

            new WhoUsesType(agg, TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.String"));
            agg.Analyze(TestConstants.BaseLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "Method match count");
            Assert.AreEqual(WhoUsesType.UsedAsMethodReturnType, agg.MethodMatches[0].Annotations.Reason);
            Assert.AreEqual(WhoUsesType.UsedAsMethodParameterReason, agg.MethodMatches[1].Annotations.Reason);
        }
Beispiel #16
0
        public void Can_Find_Type_In_Method_Argument_List_Used_As_Generic_Parameter()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWithFunctionWithGenericArguments"));

            var byteType = TypeQuery.GetTypeByName(TestConstants.DependandLibV1Assembly, "DependantLibV1.WhoUsesTypeInSignature.StructWithFunctionWithSearchedParameter");

            new WhoUsesType(agg, byteType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.MethodMatches.Count, "method match count");
            Assert.AreEqual("FuncWithGenricMethodArgs", agg.MethodMatches[0].Match.Name);
        }
Beispiel #17
0
        public void Can_Find_GenericParameters_Of_Base_Type()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWhichDerivesFromGenericBaseClass"));

            var decimalType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Decimal");

            new WhoUsesType(agg, decimalType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.TypeMatches.Count, "Type match count");
            Assert.AreEqual("DependantLibV1.WhoUsesTypeInSignature.ClassWhichDerivesFromGenericBaseClass", agg.TypeMatches[0].Match.FullName);
        }
Beispiel #18
0
        public void Can_Find_Type_As_Base_Class()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassDerivesFromException"));

            var exType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Exception");

            new WhoUsesType(agg, exType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.TypeMatches.Count, "Type match count");
            Assert.AreEqual("ClassDerivesFromException", agg.TypeMatches[0].Match.Name);
        }
Beispiel #19
0
        public void Can_Find_Genericparameters_Of_Base_Interface()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("BaseLibrary.ApiChanges", "IGenericInteface"));

            var floatType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Single");

            new WhoUsesType(agg, floatType);
            agg.Analyze(TestConstants.BaseLibV1Assembly);

            Assert.AreEqual(3, agg.TypeMatches.Count, "Type match count");
            Assert.AreEqual("BaseLibrary.ApiChanges.IGenericInteface", agg.TypeMatches[0].Match.FullName);
        }
        public void CanFindTypesThatDeriveFromGenericBaseClasses()
        {
            var genList = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Collections.Generic.List`1");

            UsageQueryAggregator agg = new UsageQueryAggregator();

            new WhoDerivesFromType(agg, genList);

            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(2, agg.TypeMatches.Count);
        }
Beispiel #21
0
        public void Can_Find_Type_As_Field_Type()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWithSearchedFieldType"));

            var charType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Char");

            new WhoUsesType(agg, charType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.FieldMatches.Count, "field match count");
            Assert.AreEqual("CharEvent", agg.FieldMatches[0].Match.Name);
        }
Beispiel #22
0
        public void Can_Find_Type_As_Base_Interface()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassImplementsInterface"));

            var iDisposable = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IDisposable");

            new WhoUsesType(agg, iDisposable);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.TypeMatches.Count, "Type match count");
            Assert.AreEqual("ClassImplementsInterface", agg.TypeMatches[0].Match.Name);
        }
Beispiel #23
0
        public void Can_Find_Type_In_Method_Argument_List()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "StructWithFunctionWithSearchedParameter"));

            var byteType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Byte");

            new WhoUsesType(agg, byteType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.MethodMatches.Count, "method match count");
            Assert.AreEqual("FuncWithByteParamter", agg.MethodMatches[0].Match.Name);
        }
Beispiel #24
0
        public void Can_Detect_Field_Read_Write_MethodCall()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWithUsingStatement"));

            new WhoUsesType(agg, TestConstants.PublicBaseClassTypeV1);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(3, agg.MethodMatches.Count, "method match count");
            Assert.AreEqual("WriteToField", agg.MethodMatches[0].Match.Name);
            Assert.AreEqual("ReadFromField", agg.MethodMatches[1].Match.Name);
            Assert.AreEqual("CallFunctionFromBaseClass", agg.MethodMatches[2].Match.Name);
        }
Beispiel #25
0
        public void Can_Find_Type_In_Constrained_Calls()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWithUsingStatement"));

            var byteType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IDisposable");

            new WhoUsesType(agg, byteType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "method match count");
            Assert.AreEqual("FunctionWithUsingStatement", agg.MethodMatches[0].Match.Name);
            Assert.AreEqual("UsingDisposeableStruct", agg.MethodMatches[1].Match.Name);
        }
Beispiel #26
0
        public void Can_Find_GenericMethodInvocations_With_Type_Parameters()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "UsageClass"));

            var decimalType = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.Decimal");

            new WhoUsesType(agg, decimalType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(2, agg.MethodMatches.Count, "Method match count");
            Assert.AreEqual("UseGenericMethod", agg.MethodMatches[0].Match.Name);
            Assert.AreEqual("UseGenericMethod", agg.MethodMatches[1].Match.Name);
        }
Beispiel #27
0
        public void Can_Find_All_Subscribers_To_Static_And_Instance_Events()
        {
            TypeDefinition         type = TypeQuery.GetTypeByName(TestConstants.BaseLibV1Assembly, "BaseLibrary.ApiChanges.PublicBaseClass");
            List <EventDefinition> evs  = new EventQuery().GetMatchingEvents(type);

            Assert.AreEqual(2, evs.Count, "Class has events defined");

            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.MethodUsage"));

            new WhoUsesEvents(agg, evs);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(3, agg.MethodMatches.Count);
        }
Beispiel #28
0
        public void Can_Find_Type_In_Method_Return_Type_In_Interface()
        {
            UsageQueryAggregator agg = new UsageQueryAggregator(new TypeQuery("DependantLibV1.WhoUsesTypeInSignature", "ClassWithGenericTypeArguments"));

            var dateTimeType = TypeQuery.GetTypeByName(
                TestConstants.MscorlibAssembly,
                "System.DateTime");

            new WhoUsesType(agg, dateTimeType);
            agg.Analyze(TestConstants.DependandLibV1Assembly);

            Assert.AreEqual(1, agg.MethodMatches.Count, "Method match count");
            Assert.AreEqual("public virtual IEnumerator<DateTime> GetEnumerator()", agg.MethodMatches[0].Match.Print(MethodPrintOption.Full));
        }
        public void Can_Differentiate_Between_Generic_Interface_Implementations()
        {
            var iGenericIComparable = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IComparable`1");
            var iIComparable        = TypeQuery.GetTypeByName(TestConstants.MscorlibAssembly, "System.IComparable");

            UsageQueryAggregator agg = new UsageQueryAggregator();

            new WhoImplementsInterface(agg, iGenericIComparable);
            new WhoImplementsInterface(agg, iIComparable);

            agg.Analyze(TestConstants.DependandLibV1Assembly);
            var results = agg.TypeMatches;

            Assert.AreEqual(2, results.Count);
        }
Beispiel #30
0
        private void SearchForImablancedEventSubscriptions(List <EventDefinition> eventsToSearch)
        {
            Writer.SetCurrentSheet(myImbalancedEventsHeader);

            LoadAssemblies(myParsedArgs.Queries2, (cecilAssembly, file) =>
            {
                using (UsageQueryAggregator aggregator = new UsageQueryAggregator(myParsedArgs.SymbolServer))
                {
                    new WhoUsesEvents(aggregator, eventsToSearch);
                    aggregator.Analyze(cecilAssembly);

                    List <EventUsage> usages = new List <EventUsage>();

                    aggregator.MethodMatches.ForEach((result) =>
                    {
                        usages.Add(new EventUsage(result));
                    });

                    var eventsgroupedbyType = from usage in usages
                                              group usage by usage.UsingType into perType
                                              select perType;

                    foreach (var usingTypes in eventsgroupedbyType)
                    {
                        //Out.WriteLine("Events used by type {0}", usingTypes.Key);

                        Dictionary <string, int> usedEvents = new Dictionary <string, int>();
                        foreach (EventUsage usedEvent in usingTypes)
                        {
                            usedEvents[usedEvent.EventDefiningEventAssembly + usedEvent.EventName] = 0;
                        }

                        foreach (var type in usingTypes)
                        {
                            usedEvents[type.FullQualifiedEventName] += type.AddRemoveCount;
                        }

                        foreach (var unbalances in from ev in usingTypes
                                 where usedEvents[ev.FullQualifiedEventName] > 0
                                 select ev)
                        {
                            //Out.WriteLine("Type {0} uses event {1} as {2}", unbalances.UsingType, unbalances.EventName, usedEvents[unbalances.EventDefiningEventAssembly + unbalances.EventName]);
                            PrintUnmatchedEvent(unbalances, usedEvents[unbalances.FullQualifiedEventName]);
                        }
                    }
                }
            });
        }
        /// <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);
        }