public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(
                (context) =>
            {
                INamedTypeSymbol iCollectionType        = WellKnownTypes.ICollection(context.Compilation);
                INamedTypeSymbol genericICollectionType = WellKnownTypes.GenericICollection(context.Compilation);
                INamedTypeSymbol iEnumerableType        = WellKnownTypes.IEnumerable(context.Compilation);
                INamedTypeSymbol genericIEnumerableType = WellKnownTypes.GenericIEnumerable(context.Compilation);
                INamedTypeSymbol iListType        = WellKnownTypes.IList(context.Compilation);
                INamedTypeSymbol genericIListType = WellKnownTypes.GenericIList(context.Compilation);

                if (iCollectionType == null && genericICollectionType == null &&
                    iEnumerableType == null && genericIEnumerableType == null &&
                    iListType == null && genericIListType == null)
                {
                    return;
                }

                context.RegisterSymbolAction(c => AnalyzeSymbol(c,
                                                                iCollectionType, genericICollectionType,
                                                                iEnumerableType, genericIEnumerableType,
                                                                iListType, genericIListType),
                                             SymbolKind.NamedType);
            });
        }
        private static ImmutableHashSet <INamedTypeSymbol> GetWellKnownCollectionTypes(Compilation compilation)
        {
            var builder     = ImmutableHashSet.CreateBuilder <INamedTypeSymbol>();
            var iCollection = WellKnownTypes.ICollection(compilation);

            if (iCollection != null)
            {
                builder.Add(iCollection);
            }

            var genericICollection = WellKnownTypes.GenericICollection(compilation);

            if (genericICollection != null)
            {
                builder.Add(genericICollection);
            }

            var genericIReadOnlyCollection = WellKnownTypes.GenericIReadOnlyCollection(compilation);

            if (genericIReadOnlyCollection != null)
            {
                builder.Add(genericIReadOnlyCollection);
            }

            return(builder.ToImmutable());
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="OperationActionsContext"/> class.
 /// </summary>
 /// <param name="compilation">The compilation.</param>
 /// <param name="enumerableType">Type of the enumerable.</param>
 public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumerableType)
 {
     Compilation               = compilation;
     EnumerableType            = enumerableType;
     _immutableArrayType       = new Lazy <INamedTypeSymbol>(() => WellKnownTypes.ImmutableArray(Compilation), true);
     _iCollectionCountProperty = new Lazy <IPropertySymbol>(ResolveICollectionCountProperty, true);
     _iCollectionOfType        = new Lazy <INamedTypeSymbol>(() => WellKnownTypes.GenericICollection(Compilation), true);
 }
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(
                (context) =>
            {
                INamedTypeSymbol iCollectionType        = WellKnownTypes.ICollection(context.Compilation);
                INamedTypeSymbol genericICollectionType = WellKnownTypes.GenericICollection(context.Compilation);
                INamedTypeSymbol arrayType           = WellKnownTypes.Array(context.Compilation);
                INamedTypeSymbol dataMemberAttribute = WellKnownTypes.DataMemberAttribute(context.Compilation);
                ImmutableHashSet <INamedTypeSymbol> immutableInterfaces = WellKnownTypes.IImmutableInterfaces(context.Compilation);

                if (iCollectionType == null ||
                    genericICollectionType == null ||
                    arrayType == null)
                {
                    return;
                }

                context.RegisterSymbolAction(c => AnalyzeSymbol(c, iCollectionType, genericICollectionType, arrayType, dataMemberAttribute, immutableInterfaces), SymbolKind.Property);
            });
        }
示例#5
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.RegisterCompilationStartAction(compilationContext =>
            {
                var iDisposable = WellKnownTypes.IDisposable(compilationContext.Compilation);
                if (iDisposable == null)
                {
                    return;
                }

                var iCollection        = WellKnownTypes.ICollection(compilationContext.Compilation);
                var genericICollection = WellKnownTypes.GenericICollection(compilationContext.Compilation);
                var disposeOwnershipTransferLikelyTypes = GetDisposeOwnershipTransferLikelyTypes(compilationContext.Compilation);
                compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext =>
                {
                    bool hasDisposableCreation = false;
                    operationBlockStartContext.RegisterOperationAction(operationContext =>
                    {
                        if (!hasDisposableCreation &&
                            operationContext.Operation.Type.IsDisposable(iDisposable))
                        {
                            hasDisposableCreation = true;
                        }
                    },
                                                                       OperationKind.ObjectCreation,
                                                                       OperationKind.TypeParameterObjectCreation,
                                                                       OperationKind.DynamicObjectCreation,
                                                                       OperationKind.Invocation);

                    operationBlockStartContext.RegisterOperationBlockEndAction(operationBlockEndContext =>
                    {
                        if (!hasDisposableCreation ||
                            !(operationBlockEndContext.OwningSymbol is IMethodSymbol containingMethod))
                        {
                            return;
                        }

                        foreach (var operationRoot in operationBlockEndContext.OperationBlocks)
                        {
                            IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock();
                            if (topmostBlock != null)
                            {
                                var cfg = ControlFlowGraph.Create(topmostBlock);
                                var nullAnalysisResult     = NullAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType);
                                var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType, nullAnalysisResult);
                                var disposeAnalysisResult  = DisposeAnalysis.GetOrComputeResult(cfg, iDisposable, iCollection,
                                                                                                genericICollection, disposeOwnershipTransferLikelyTypes, containingMethod.ContainingType, pointsToAnalysisResult, nullAnalysisResult);
                                ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeDataAtExit = disposeAnalysisResult[cfg.Exit].InputData;
                                foreach (var kvp in disposeDataAtExit)
                                {
                                    AbstractLocation location         = kvp.Key;
                                    DisposeAbstractValue disposeValue = kvp.Value;
                                    if (disposeValue.Kind == DisposeAbstractValueKind.NotDisposed ||
                                        ((disposeValue.Kind == DisposeAbstractValueKind.Disposed ||
                                          disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed) &&
                                         disposeValue.DisposingOperations.Count > 0 &&
                                         disposeValue.DisposingOperations.All(d => d.IsInsideCatchClause())))
                                    {
                                        Debug.Assert(location.CreationOpt != null);

                                        // CA2000: In method '{0}', call System.IDisposable.Dispose on object created by '{1}' before all references to it are out of scope.
                                        var arg1       = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
                                        var arg2       = location.CreationOpt.Syntax.ToString();
                                        var diagnostic = location.CreationOpt.Syntax.CreateDiagnostic(Rule, arg1, arg2);
                                        operationBlockEndContext.ReportDiagnostic(diagnostic);
                                    }
                                }

                                break;
                            }
                        }
                    });
                });
            });
        }