private void ProcessEventDefinition(EventDefinition eventDefinition, IntertypeRelationGraph graph, TypeDefinition type)
        {
            if (eventDefinition.AddMethod != null)
            {
                ProcessMethodDefinition(eventDefinition.AddMethod, graph, type);
            }
            if (eventDefinition.RemoveMethod != null)
            {
                ProcessMethodDefinition(eventDefinition.RemoveMethod, graph, type);
            }
            if (eventDefinition.InvokeMethod != null)
            {
                ProcessMethodDefinition(eventDefinition.InvokeMethod, graph, type);
            }
            if (eventDefinition.HasOtherMethods)
            {
                foreach (var methodDef in eventDefinition.OtherMethods)
                {
                    ProcessMethodDefinition(methodDef, graph, type);
                }
            }
            AddUseEdgeIfBothExist(type, eventDefinition.EventType, graph);

            if (eventDefinition.HasCustomAttributes)
            {
                foreach (var attribute in eventDefinition.CustomAttributes)
                {
                    AddUseEdgeIfBothExist(type, attribute.AttributeType, graph);
                }
            }
        }
        private void AddNodeIfNotExists(INamespaceOrTypeSymbol namedType, IntertypeRelationGraph graph, List <INamedTypeSymbol> typeSymbols)
        {
            if (namedType == null)
            {
                return;
            }

            if (namedType.IsType)
            {
                typeSymbols.Add((INamedTypeSymbol)namedType);

                var typeName = GetTypeIdentifier(namedType);
                if (!graph.Nodes.Contains(typeName))
                {
                    graph.Nodes.Add(typeName);
                }
            }
            else
            {
                foreach (var type in namedType.GetMembers())
                {
                    AddNodeIfNotExists(type as INamespaceOrTypeSymbol, graph, typeSymbols);
                }
            }
        }
 private void ProcessAttributes(INamedTypeSymbol type, ISymbol symbol, IntertypeRelationGraph graph)
 {
     foreach (var attribute in symbol.GetAttributes())
     {
         AddUseEdgeIfBothExist(type, attribute.AttributeClass, graph);
     }
 }
        private void AddNodeIfNotAlreadyThere(TypeDefinition type, IntertypeRelationGraph graph, List <TypeDefinition> typeDefinitions)
        {
            if (!graph.Nodes.Contains(type.FullName) && !type.IsAnonymousType())
            {
                typeDefinitions.Add(type);

                graph.Nodes.Add(type.FullName);
            }
        }
 private void ProcessTypeDefinition(TypeDefinition type, IntertypeRelationGraph graph)
 {
     if (type.BaseType != null)
     {
         AddInheritanceEdgeIfBothExist(type, type.BaseType, graph);
     }
     if (type.HasInterfaces)
     {
         foreach (var interfaceDef in type.Interfaces)
         {
             AddInheritanceEdgeIfBothExist(type, interfaceDef.InterfaceType, graph);
         }
     }
     if (type.HasMethods)
     {
         foreach (var method in type.Methods)
         {
             ProcessMethodDefinition(method, graph, type);
         }
     }
     if (type.HasProperties)
     {
         foreach (var property in type.Properties)
         {
             ProcessPropertyDefinition(property, graph, type);
         }
     }
     if (type.HasFields)
     {
         foreach (var field in type.Fields)
         {
             ProcessFieldDefinition(field, graph, type);
         }
     }
     if (type.HasEvents)
     {
         foreach (var eventDef in type.Events)
         {
             ProcessEventDefinition(eventDef, graph, type);
         }
     }
     if (type.HasGenericParameters)
     {
         foreach (var genericParameter in type.GenericParameters)
         {
             ProcessGenericParameter(genericParameter, graph, type);
         }
     }
     if (type.HasCustomAttributes)
     {
         foreach (var attribute in type.CustomAttributes)
         {
             AddUseEdgeIfBothExist(type, attribute.AttributeType, graph);
         }
     }
 }
 private void ProcessGenericParameter(GenericParameter genericParameter, IntertypeRelationGraph graph, TypeDefinition type)
 {
     if (genericParameter.HasConstraints)
     {
         foreach (var constraint in genericParameter.Constraints)
         {
             AddUseEdgeIfBothExist(type, constraint, graph);
         }
     }
 }
 private void AddNestedTypes(TypeDefinition type, IntertypeRelationGraph graph, List <TypeDefinition> typeDefinitions)
 {
     if (type.HasNestedTypes)
     {
         foreach (var nestedType in type.NestedTypes)
         {
             AddNodeIfNotAlreadyThere(nestedType, graph, typeDefinitions);
             AddNestedTypes(nestedType, graph, typeDefinitions);
         }
     }
 }
        private void ProcessFieldDefinition(FieldDefinition fieldDefinition, IntertypeRelationGraph graph, TypeDefinition type)
        {
            AddUseEdgeIfBothExist(type, fieldDefinition.FieldType, graph);

            if (fieldDefinition.HasCustomAttributes)
            {
                foreach (var attribute in fieldDefinition.CustomAttributes)
                {
                    AddUseEdgeIfBothExist(type, attribute.AttributeType, graph);
                }
            }
        }
        private void ProcessTypeSymbol(INamedTypeSymbol type, IntertypeRelationGraph graph)
        {
            if (type.BaseType != null)
            {
                AddInheritanceEdgeIfBothExist(type, type.BaseType, graph);
            }

            foreach (var typeInterface in type.Interfaces)
            {
                AddInheritanceEdgeIfBothExist(type, typeInterface, graph);
            }

            ProcessAttributes(type, type, graph);

            foreach (var symbol in type.GetMembers())
            {
                ProcessAttributes(type, symbol, graph);

                foreach (var typeParameter in type.TypeParameters)
                {
                    foreach (var constraint in typeParameter.ConstraintTypes)
                    {
                        AddUseEdgeIfBothExist(type, constraint as INamedTypeSymbol, graph);
                    }
                }

                var method = symbol as IMethodSymbol;
                if (method != null)
                {
                    ProcessMethodSymbol(type, method, graph);
                }

                var property = symbol as IPropertySymbol;
                if (property != null)
                {
                    ProcessPropertySymbol(type, property, graph);
                }

                var field = symbol as IFieldSymbol;
                if (field != null)
                {
                    ProcessFieldSymbol(type, field, graph);
                }

                var eventSymbol = symbol as IEventSymbol;
                if (eventSymbol != null)
                {
                    ProcessEventSymbol(type, eventSymbol, graph);
                }
            }
        }
        public Task <IntertypeRelationGraph> GetDataStructure(TCSharpModel model, CancellationToken cancellationToken)
        {
            var assemblies = assembliesArtefactAdapter.Parse(model.AbsoluteSolutionPath);

            var graph           = new IntertypeRelationGraph();
            var typeDefinitions = new List <TypeDefinition>();

            //First Collect All Types as Nodes
            foreach (var assembly in assemblies)
            {
                if (!File.Exists(assembly.AbsolutePath))
                {
                    continue;
                }

                var moduleDefinition = ModuleDefinition.ReadModule(assembly.AbsolutePath);
                foreach (var type in moduleDefinition.Types)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    if (type.Name == MonoModuleTyp)
                    {
                        continue;
                    }

                    AddNodeIfNotAlreadyThere(type, graph, typeDefinitions);

                    AddNestedTypes(type, graph, typeDefinitions);
                }
            }

            //Second, Build Edges
            var parallelOptions = new ParallelOptions
            {
                CancellationToken      = cancellationToken,
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            Parallel.ForEach(typeDefinitions, parallelOptions, type =>
            {
                parallelOptions.CancellationToken.ThrowIfCancellationRequested();
                ProcessTypeDefinition(type, graph);
            });

            return(Task.FromResult(graph));
        }
        public async Task <IntertypeRelationGraph> GetDataStructure(TCSharpModel model, CancellationToken token)
        {
            var graph     = new IntertypeRelationGraph();
            var workspace = MSBuildWorkspace.Create(new Dictionary <string, string>
            {
                { "Configuration", settingsProvider.Configuration },
                { "Platform", settingsProvider.Platform }
            });

            var solution = await workspace.OpenSolutionAsync(model.AbsoluteSolutionPath, token);

            compilations = new List <Compilation>();

            var typeSymbols = new List <INamedTypeSymbol>();

            //Collect all types
            foreach (var project in solution.Projects)
            {
                token.ThrowIfCancellationRequested();

                var compilation = await project.GetCompilationAsync(token);

                compilations.Add(compilation);

                foreach (var namespaceSymbol in compilation.Assembly.GlobalNamespace.GetNamespaceMembers())
                {
                    AddNodeIfNotExists(namespaceSymbol, graph, typeSymbols);
                }
            }

            //Build edges
            var parallelOptions = new ParallelOptions
            {
                CancellationToken      = token,
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };

            Parallel.ForEach(typeSymbols, parallelOptions, type =>
            {
                parallelOptions.CancellationToken.ThrowIfCancellationRequested();
                ProcessTypeSymbol(type, graph);
            });

            return(graph);
        }
        private void ProcessMethodDefinition(MethodDefinition methodDefinition, IntertypeRelationGraph graph, TypeDefinition currentType)
        {
            if (methodDefinition.HasParameters)
            {
                //Uses all parameter types
                foreach (var parameter in methodDefinition.Parameters)
                {
                    AddUseEdgeIfBothExist(currentType, parameter.ParameterType, graph);
                }
            }
            //Uses return type
            AddUseEdgeIfBothExist(currentType, methodDefinition.ReturnType, graph);

            if (methodDefinition.HasBody)
            {
                //Uses all local variable types
                foreach (var variableDefinition in methodDefinition.Body.Variables)
                {
                    AddUseEdgeIfBothExist(currentType, variableDefinition.VariableType, graph);
                }

                foreach (var instruction in methodDefinition.Body.Instructions)
                {
                    ProcessInstruction(instruction, graph, currentType);
                }
            }

            if (methodDefinition.HasGenericParameters)
            {
                foreach (var genericParameter in methodDefinition.GenericParameters)
                {
                    ProcessGenericParameter(genericParameter, graph, currentType);
                }
            }

            if (methodDefinition.HasCustomAttributes)
            {
                foreach (var attribute in methodDefinition.CustomAttributes)
                {
                    AddUseEdgeIfBothExist(currentType, attribute.AttributeType, graph);
                }
            }
        }
Esempio n. 13
0
        public ISet <TTestCase> SelectTests(IntertypeRelationGraph dataStructure, StructuralDelta <TestsModel <TTestCase>, TTestCase> testsDelta, StructuralDelta <CSharpClassesProgramModel, CSharpClassElement> programDelta, CancellationToken cancellationToken)
        {
            ISet <ImpactedTest <TTestCase> > impactedTests = new HashSet <ImpactedTest <TTestCase> >();

            var changedTypes = new List <AffectedType>();

            changedTypes.AddRange(programDelta.AddedElements.Select(x => new AffectedType {
                Id = x.Id, ImpactedDueTo = x.Id
            }));
            changedTypes.AddRange(programDelta.ChangedElements.Select(x => new AffectedType {
                Id = x.Id, ImpactedDueTo = x.Id
            }));

            var affectedTypes = new List <AffectedType>(changedTypes);

            foreach (var type in changedTypes)
            {
                cancellationToken.ThrowIfCancellationRequested();
                ExtendAffectedTypesAndReportImpactedTests(type, dataStructure, affectedTypes, testsDelta.NewModel.TestSuite, impactedTests, cancellationToken);
            }

            testsDelta.AddedElements.ForEach(x =>
            {
                if (impactedTests.All(y => y.TestCase.Id != x.Id))
                {
                    impactedTests.Add(new ImpactedTest <TTestCase> {
                        TestCase = x, ImpactedDueTo = null
                    });
                }
            });

            CorrespondenceModel = new CorrespondenceModel.Models.CorrespondenceModel
            {
                ProgramVersionId         = programDelta.NewModel.VersionId,
                CorrespondenceModelLinks = impactedTests.ToDictionary(
                    x => x.TestCase.Id,
                    x => x.ImpactedDueTo == null ? new HashSet <string>() : new HashSet <string>(new[] { x.ImpactedDueTo }))
            };

            return(new HashSet <TTestCase>(impactedTests.Select(x => x.TestCase)));
        }
        private void ProcessInstruction(Instruction instruction, IntertypeRelationGraph graph, TypeDefinition currentType)
        {
            if (instruction.Operand == null)
            {
                return;
            }

            var typeRef = instruction.Operand as TypeReference;

            if (typeRef != null)
            {
                AddUseEdgeIfBothExist(currentType, typeRef, graph);
            }

            var memberRef = instruction.Operand as MemberReference;

            if (memberRef != null)
            {
                AddUseEdgeIfBothExist(currentType, memberRef.DeclaringType, graph);
            }
        }
 private void AddUseEdgeIfBothExist(TypeDefinition from, TypeReference to, IntertypeRelationGraph graph)
 {
     AddEdgeIfBothExist(from, to, true, graph);
 }
 private void AddInheritanceEdgeIfBothExist(TypeDefinition from, TypeReference to, IntertypeRelationGraph graph)
 {
     AddEdgeIfBothExist(from, to, false, graph);
 }
 private void ProcessFieldSymbol(INamedTypeSymbol type, IFieldSymbol field, IntertypeRelationGraph graph)
 {
     AddUseEdgeIfBothExist(type, field.Type as INamedTypeSymbol, graph);
 }
        private void AddEdgeIfBothExist(INamedTypeSymbol from, INamedTypeSymbol to, bool useEdge, IntertypeRelationGraph graph)
        {
            if (from == null || to == null || from.TypeKind == TypeKind.Error || to.TypeKind == TypeKind.Error || Equals(from, to))
            {
                return;
            }

            if (to.IsGenericType)
            {
                foreach (var genericArugment in to.TypeArguments)
                {
                    AddUseEdgeIfBothExist(from, genericArugment as INamedTypeSymbol, graph);
                }
            }
            var fromName = GetTypeIdentifier(from);
            var toName   = GetTypeIdentifier(to);

            if (!graph.Nodes.Contains(fromName) || !graph.Nodes.Contains(toName))
            {
                return;
            }

            if (useEdge)
            {
                graph.AddUseEdgeIfNotExists(fromName, toName);
            }
            else
            {
                graph.AddInheritanceEdgeIfNotExists(fromName, toName);
            }
        }
 private void AddUseEdgeIfBothExist(INamedTypeSymbol from, INamedTypeSymbol to, IntertypeRelationGraph graph)
 {
     AddEdgeIfBothExist(from, to, true, graph);
 }
 private void AddInheritanceEdgeIfBothExist(INamedTypeSymbol from, INamedTypeSymbol to, IntertypeRelationGraph graph)
 {
     AddEdgeIfBothExist(from, to, false, graph);
 }
        private void ProcessOperations(SemanticModel semanticModel, INamedTypeSymbol type, IntertypeRelationGraph graph, SyntaxNode node)
        {
            IOperation operation = semanticModel.GetOperation(node);

            ProcessOperation(type, operation, graph);
        }
        private void AddEdgeIfBothExist(TypeDefinition from, TypeReference to, bool useEdge, IntertypeRelationGraph graph)
        {
            if (from == null || to == null)
            {
                return;
            }

            var genericType = to as GenericInstanceType;

            if (genericType != null && genericType.HasGenericArguments)
            {
                foreach (var genericArgument in genericType.GenericArguments)
                {
                    AddUseEdgeIfBothExist(from, genericArgument, graph);
                }
            }

            if (!graph.Nodes.Contains(from.FullName) || !graph.Nodes.Contains(to.FullName))
            {
                return;
            }

            if (useEdge)
            {
                graph.AddUseEdgeIfNotExists(from.FullName, to.FullName);
            }
            else
            {
                graph.AddInheritanceEdgeIfNotExists(from.FullName, to.FullName);
            }
        }
        private void ProcessPropertySymbol(INamedTypeSymbol type, IPropertySymbol property, IntertypeRelationGraph graph)
        {
            AddUseEdgeIfBothExist(type, property.Type as INamedTypeSymbol, graph);

            ProcessMethodSymbol(type, property.SetMethod, graph);
            ProcessMethodSymbol(type, property.GetMethod, graph);
        }
        private void ProcessMethodSymbol(INamedTypeSymbol type, IMethodSymbol method, IntertypeRelationGraph graph)
        {
            if (method == null)             //Get or Set Method e.g. are not necessarily implemented
            {
                return;
            }

            foreach (var methodParameter in method.Parameters)
            {
                AddUseEdgeIfBothExist(type, methodParameter.Type as INamedTypeSymbol, graph);
            }

            AddUseEdgeIfBothExist(type, method.ReturnType as INamedTypeSymbol, graph);

            foreach (var typeParameter in method.TypeParameters)
            {
                foreach (var constraint in typeParameter.ConstraintTypes)
                {
                    AddUseEdgeIfBothExist(type, constraint as INamedTypeSymbol, graph);
                }
            }

            foreach (var methodDeclaringSyntaxReference in method.DeclaringSyntaxReferences)
            {
                var methodSyntax = methodDeclaringSyntaxReference.GetSyntax();
                var compilation  = compilations.First(x => Equals(x.Assembly, method.ContainingAssembly));

                var semanticModel = compilation.GetSemanticModel(methodSyntax.SyntaxTree);

                var accessorDec = methodSyntax as AccessorDeclarationSyntax;                 //Properties
                if (accessorDec?.Body != null)
                {
                    ProcessOperations(semanticModel, type, graph, accessorDec.Body);
                    continue;
                }

                var arrowExpr = methodSyntax as ArrowExpressionClauseSyntax;                 //Properties with Arrow
                if (arrowExpr?.Expression != null)
                {
                    ProcessOperations(semanticModel, type, graph, arrowExpr.Expression);
                    continue;
                }

                var methodDec = methodSyntax as BaseMethodDeclarationSyntax;                 //Methods, Constructors
                if (methodDec?.Body != null)
                {
                    ProcessOperations(semanticModel, type, graph, methodDec.Body);
                }
            }
        }
        private void ProcessPropertyDefinition(PropertyDefinition propertyDefinition, IntertypeRelationGraph graph, TypeDefinition currentType)
        {
            if (propertyDefinition.SetMethod != null)
            {
                ProcessMethodDefinition(propertyDefinition.SetMethod, graph, currentType);
            }
            if (propertyDefinition.GetMethod != null)
            {
                ProcessMethodDefinition(propertyDefinition.GetMethod, graph, currentType);
            }
            AddUseEdgeIfBothExist(currentType, propertyDefinition.PropertyType, graph);

            if (propertyDefinition.HasCustomAttributes)
            {
                foreach (var attribute in propertyDefinition.CustomAttributes)
                {
                    AddUseEdgeIfBothExist(currentType, attribute.AttributeType, graph);
                }
            }
        }
        private void ProcessOperation(INamedTypeSymbol type, IOperation operation, IntertypeRelationGraph graph)
        {
            foreach (var child in operation.Children)
            {
                ProcessOperation(type, child, graph);
            }

            //AddUseEdgeIfBothExist(type, operation.Type as INamedTypeSymbol, graph);

            switch (operation.Kind)
            {
            case OperationKind.DynamicMemberReference:
                var dynmemberRef = (IDynamicMemberReferenceOperation)operation;
                AddUseEdgeIfBothExist(type, dynmemberRef.ContainingType as INamedTypeSymbol, graph);
                foreach (var typeArg in dynmemberRef.TypeArguments)
                {
                    AddUseEdgeIfBothExist(type, typeArg as INamedTypeSymbol, graph);
                }
                break;

            case OperationKind.EventReference:
            case OperationKind.FieldReference:
            case OperationKind.MethodReference:
            case OperationKind.PropertyReference:
                var memberReference = (IMemberReferenceOperation)operation;
                AddUseEdgeIfBothExist(type, memberReference.Member.ContainingType, graph);
                AddUseEdgeIfBothExist(type, memberReference.Member.ContainingType, graph);
                break;

            case OperationKind.TypeOf:
                var typeOfOp = (ITypeOfOperation)operation;
                AddUseEdgeIfBothExist(type, typeOfOp.TypeOperand as INamedTypeSymbol, graph);
                break;

            case OperationKind.ObjectCreation:
                var objectCreation = (IObjectCreationOperation)operation;
                AddUseEdgeIfBothExist(type, objectCreation.Constructor?.ContainingType, graph);
                break;

            case OperationKind.IsType:
                var isType = (IIsTypeOperation)operation;
                AddUseEdgeIfBothExist(type, isType.TypeOperand as INamedTypeSymbol, graph);
                break;

            case OperationKind.Tuple:
                var tuple = (ITupleOperation)operation;
                AddUseEdgeIfBothExist(type, tuple.NaturalType as INamedTypeSymbol, graph);
                break;

            case OperationKind.SizeOf:
                var sizeOf = (ISizeOfOperation)operation;
                AddUseEdgeIfBothExist(type, sizeOf.TypeOperand as INamedTypeSymbol, graph);
                break;

            case OperationKind.FieldInitializer:
                var fieldInit = (IFieldInitializerOperation)operation;
                foreach (var initializedField in fieldInit.InitializedFields)
                {
                    AddUseEdgeIfBothExist(type, initializedField.Type as INamedTypeSymbol, graph);
                }
                break;

            case OperationKind.PropertyInitializer:
                var propertyInit = (IPropertyInitializerOperation)operation;
                foreach (var initProperty in propertyInit.InitializedProperties)
                {
                    AddUseEdgeIfBothExist(type, initProperty.Type as INamedTypeSymbol, graph);
                }
                break;

            case OperationKind.ParameterInitializer:
                var paramInit = (IParameterInitializerOperation)operation;
                AddUseEdgeIfBothExist(type, paramInit.Parameter.ContainingType, graph);
                break;

            case OperationKind.VariableDeclarator:
                var variableDeclarator = (IVariableDeclaratorOperation)operation;
                AddUseEdgeIfBothExist(type, variableDeclarator.Symbol.Type as INamedTypeSymbol, graph);
                break;

            case OperationKind.Argument:
                var argumentOperation = (IArgumentOperation)operation;
                AddUseEdgeIfBothExist(type, argumentOperation.Parameter.Type as INamedTypeSymbol, graph);
                break;

            case OperationKind.CatchClause:
                var catchClause = (ICatchClauseOperation)operation;
                AddUseEdgeIfBothExist(type, catchClause.ExceptionType as INamedTypeSymbol, graph);
                break;

            case OperationKind.DeclarationPattern:
                var declarationpattern = (IDeclarationPatternOperation)operation;
                AddUseEdgeIfBothExist(type, declarationpattern.DeclaredSymbol as INamedTypeSymbol, graph);
                break;

            case OperationKind.Invocation:
                var incovation = (IInvocationOperation)operation;
                AddUseEdgeIfBothExist(type, incovation.TargetMethod?.ContainingType, graph);
                break;
            }
        }
Esempio n. 27
0
        private void ExtendAffectedTypesAndReportImpactedTests(AffectedType type, IntertypeRelationGraph graph, List <AffectedType> affectedTypes, ISet <TTestCase> allTests, ISet <ImpactedTest <TTestCase> > impactedTests, CancellationToken cancellationToken)
        {
            foreach (var test in allTests.Where(x => x.AssociatedClasses.Contains(type.Id)))
            {
                if (impactedTests.All(y => y.TestCase.Id != test.Id))
                {
                    impactedTests.Add(new ImpactedTest <TTestCase> {
                        TestCase = test, ImpactedDueTo = type.ImpactedDueTo
                    });
                }
            }

            var usedByTypes = graph.UseEdges.Where(x => x.Item2 == type.Id).Select(x => x.Item1);

            foreach (string usedByType in usedByTypes)
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (affectedTypes.All(x => x.Id != usedByType))
                {
                    var newAffectedType = new AffectedType {
                        Id = usedByType, ImpactedDueTo = type.ImpactedDueTo
                    };
                    affectedTypes.Add(newAffectedType);
                    ExtendAffectedTypesAndReportImpactedTests(newAffectedType, graph, affectedTypes, allTests, impactedTests, cancellationToken);
                }
            }

            // https://dl.acm.org/citation.cfm?id=2950361
            // Section 2.1 Class-Level Static RTS (ClassSRTS)
            // "Note that ClassSRTS need not include supertypes of the changed types (but must include all subtypes)
            // in the transitive closure because a test cannot be affected statically by the changes even if the
            // test reaches supertype(s) of the changed types unless the test also reaches a changed type or (one of) its subtypes."
            var subTypes = graph.InheritanceEdges.Where(x => x.Item2 == type.Id).Select(x => x.Item1);

            foreach (string subtype in subTypes)
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (affectedTypes.All(x => x.Id != subtype))
                {
                    var newAffectedType = new AffectedType {
                        Id = subtype, ImpactedDueTo = type.ImpactedDueTo
                    };
                    affectedTypes.Add(newAffectedType);
                    ExtendAffectedTypesAndReportImpactedTests(newAffectedType, graph, affectedTypes, allTests, impactedTests, cancellationToken);
                }
            }

            //However, this might not be true if dependency injection is used:
            //Instances of objects are injected dynamically which happens out of scope of the static analysis
            //-> Pessimistic approach selects also all super types
            var superTypes = graph.InheritanceEdges.Where(x => x.Item1 == type.Id).Select(x => x.Item2);

            foreach (string superType in superTypes)
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (affectedTypes.All(x => x.Id != superType))
                {
                    var newAffectedType = new AffectedType {
                        Id = superType, ImpactedDueTo = type.ImpactedDueTo
                    };
                    affectedTypes.Add(newAffectedType);
                    ExtendAffectedTypesAndReportImpactedTests(newAffectedType, graph, affectedTypes, allTests, impactedTests, cancellationToken);
                }
            }
        }
 private void ProcessEventSymbol(INamedTypeSymbol type, IEventSymbol eventSymbol, IntertypeRelationGraph graph)
 {
     ProcessMethodSymbol(type, eventSymbol.AddMethod, graph);
     ProcessMethodSymbol(type, eventSymbol.RemoveMethod, graph);
     ProcessMethodSymbol(type, eventSymbol.RaiseMethod, graph);
     AddUseEdgeIfBothExist(type, eventSymbol.Type as INamedTypeSymbol, graph);
 }