/// <summary> /// Finds types that have a dependency on every items in a given list of dependencies. /// </summary> /// <param name="input">The set of type definitions to search.</param> /// <param name="dependencies">The set of dependencies to look for.</param> /// <returns>A list of dependencies found in the input classes.</returns> internal IReadOnlyList <TypeDefinition> FindTypesWithAllDependencies(IEnumerable <TypeDefinition> input, IEnumerable <string> dependencies) { // Set up the search definition var results = new SearchDefinition(dependencies); // Check each type in turn foreach (var type in input) { CheckType(type, ref results); } var output = new List <TypeDefinition>(); foreach (var typeFound in results.TypesFound) { // NB: Nested classes won't be picked up here var match = input.FirstOrDefault(d => d.FullName.Equals(typeFound, StringComparison.InvariantCultureIgnoreCase)); if (match != null && results.GetAllDependenciesMatchingAnyOf(results.GetDependenciesFoundForType(typeFound)).Count() == results.UniqueDependenciesCount) { // Check found output.Add(match); } } return(output); }
/// <summary> /// Finds matching dependencies for a given method by scanning the code. /// </summary> private void CheckMethodBody(TypeDefinition type, MethodDefinition method, ref SearchDefinition results) { if (method.HasBody) { foreach (var variable in method.Body.Variables) { // Check any nested types in methods - the compiler will create one for every asynchronous method or iterator. if (variable.VariableType.IsNested) { CheckType(variable.VariableType.Resolve(), ref results); } else { if (variable.VariableType.ContainsGenericParameter) { CheckParameters(type, variable.VariableType.GenericParameters, ref results); } if (results.GetAllMatchingDependencies(variable.VariableType.FullName).Any()) { results.AddToFound(type, variable.VariableType.FullName); } } } // Check each instruction for references to our types foreach (var instruction in method.Body.Instructions) { if (instruction.Operand != null) { var operands = ExtractTypeNames(instruction.Operand.ToString()); var matches = results.GetAllDependenciesMatchingAnyOf(operands); foreach (var item in matches) { results.AddToFound(type, item); } } } } }
/// <summary> /// Finds matching dependencies for a set of generic or not parameters /// </summary> private void CheckParameters(TypeDefinition type, IEnumerable <TypeReference> parameters, ref SearchDefinition results) { foreach (var parameter in parameters) { if (IsTypeGeneric(parameter.FullName)) { var types = ExtractTypeNames(parameter.FullName); var matches = results.GetAllDependenciesMatchingAnyOf(types); foreach (var item in matches) { results.AddToFound(type, item); } } else { if (results.GetAllMatchingDependencies(parameter.FullName).Any()) { results.AddToFound(type, parameter.FullName); } } } }