private static void OnSymbolStart(SymbolStartAnalysisContext symbolStartContext)
        {
            if (!DisposeAnalysisHelper.TryGetOrCreate(symbolStartContext.Compilation, out DisposeAnalysisHelper? disposeAnalysisHelper) ||
                !ShouldAnalyze(symbolStartContext, disposeAnalysisHelper))
            {
                return;
            }

            var fieldDisposeValueMap = PooledConcurrentDictionary <IFieldSymbol, /*disposed*/ bool> .GetInstance();

            var hasErrors = false;

            symbolStartContext.RegisterOperationAction(_ => hasErrors = true, OperationKind.Invalid);

            // Disposable fields with initializer at declaration must be disposed.
            symbolStartContext.RegisterOperationAction(OnFieldInitializer, OperationKind.FieldInitializer);

            // Instance fields initialized in constructor/method body with a locally created disposable object must be disposed.
            symbolStartContext.RegisterOperationBlockStartAction(OnOperationBlockStart);

            // Report diagnostics at symbol end.
            symbolStartContext.RegisterSymbolEndAction(OnSymbolEnd);

            return;

            // Local functions
            void AddOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed)
            {
                Debug.Assert(!field.IsStatic);
                Debug.Assert(disposeAnalysisHelper !.IsDisposable(field.Type));

                fieldDisposeValueMap.AddOrUpdate(field,
                                                 addValue: disposed,
                                                 updateValueFactory: (f, currentValue) => currentValue || disposed);
            }
Пример #2
0
            public static void OnSymbolStart(SymbolStartAnalysisContext symbolStartContext, DisposeAnalysisHelper disposeAnalysisHelper)
            {
                // We only want to analyze types which are disposable (implement System.IDisposable directly or indirectly)
                // and have at least one disposable field.
                var namedType = (INamedTypeSymbol)symbolStartContext.Symbol;

                if (!namedType.IsDisposable(disposeAnalysisHelper.IDisposableType))
                {
                    return;
                }

                var disposableFields = disposeAnalysisHelper.GetDisposableFields(namedType);

                if (disposableFields.IsEmpty)
                {
                    return;
                }

                var analyzer = new SymbolAnalyzer(disposableFields, disposeAnalysisHelper);

                // Register an operation block action to analyze disposable assignments and dispose invocations for fields.
                symbolStartContext.RegisterOperationBlockStartAction(analyzer.OnOperationBlockStart);

                // Register symbol end action for containing type to report non-disposed fields.
                // We report fields that have disposable type (implement System.IDisposable directly or indirectly)
                // and were assigned a disposable object within this containing type, but were not disposed in
                // containing type's Dispose method.
                symbolStartContext.RegisterSymbolEndAction(analyzer.OnSymbolEnd);
            }
 // Actions/Symbol
 private static void OnSymbol_Start(SymbolStartAnalysisContext context)   // for specific SymbolKind
 //// CodeBlock
 //context.RegisterCodeBlockStartAction<SyntaxKind>( OnCodeBlock_Start );
 //context.RegisterCodeBlockAction( OnCodeBlock );
 // Symbol
 {
     context.RegisterSymbolEndAction(OnSymbol_End);
 }
 static bool ShouldAnalyze(SymbolStartAnalysisContext symbolStartContext, DisposeAnalysisHelper disposeAnalysisHelper)
 {
     // We only want to analyze types which are disposable (implement System.IDisposable directly or indirectly)
     // and have at least one disposable field.
     var namedType = (INamedTypeSymbol)symbolStartContext.Symbol;
     return disposeAnalysisHelper.IsDisposable(namedType) &&
         !disposeAnalysisHelper.GetDisposableFields(namedType).IsEmpty &&
         !namedType.IsConfiguredToSkipAnalysis(symbolStartContext.Options, Rule, symbolStartContext.Compilation, symbolStartContext.CancellationToken);
 }
 private void RegisterActions(SymbolStartAnalysisContext symbolStartContext)
 {
     symbolStartContext.RegisterOperationBlockStartAction(blockAction =>
     {
         var isConstructor = blockAction.OwningSymbol is IMethodSymbol method &&
                             method.MethodKind == MethodKind.Constructor;
         blockAction.RegisterOperationAction(
             operationAction => AnalyzeAssignment(operationAction, isConstructor), OperationKind.SimpleAssignment);
     });
     symbolStartContext.RegisterSymbolEndAction(SymbolEndAction);
 }
Пример #6
0
            private void RegisterActions(SymbolStartAnalysisContext context)
            {
                context.RegisterOperationBlockStartAction(context =>
                {
                    if (context.OwningSymbol is IMethodSymbol {
                        MethodKind: MethodKind.Constructor
                    })
                    {
                        // We are looking for assignment to 'this' outside the constructor scope
                        return;
                    }

                    context.RegisterOperationAction(AnalyzeAssignment, OperationKind.SimpleAssignment);
                });
 private void OnSymbolStart(SymbolStartAnalysisContext context)
 {
     context.RegisterOperationBlockStartAction(OnOperationBlock);
     context.RegisterSymbolEndAction(OnSymbolEnd);
 }
Пример #8
0
 /// <summary>
 /// Override this method to register custom language specific actions to find symbol usages.
 /// </summary>
 protected virtual void HandleNamedTypeSymbolStart(SymbolStartAnalysisContext context, Action <ISymbol, ValueUsageInfo> onSymbolUsageFound)
 {
 }
 // Actions/Symbol
 private static void OnSymbol_Start(SymbolStartAnalysisContext context)   // for specific SymbolKind
 {
     context.RegisterSymbolEndAction(OnSymbol_End);
 }
Пример #10
0
            static void OnSymbolStart(
                SymbolStartAnalysisContext symbolStartContext,
                WellKnownTypeProvider wellKnownTypeProvider,
                ImmutableArray <INamedTypeSymbol> skippedAttributes,
                bool isWebProject)
            {
                // Since property/event accessors cannot be marked static themselves and the associated symbol (property/event)
                // has to be marked static, we want to report the diagnostic on the property/event.
                // So we make a note of the property/event symbols which have at least one accessor with no instance access.
                // At symbol end, we report candidate property/event symbols whose all accessors are candidates to be marked static.
                var propertyOrEventCandidates = PooledConcurrentSet <ISymbol> .GetInstance();

                var accessorCandidates = PooledConcurrentSet <IMethodSymbol> .GetInstance();

                var methodCandidates = PooledConcurrentSet <IMethodSymbol> .GetInstance();

                // Do not flag methods that are used as delegates: https://github.com/dotnet/roslyn-analyzers/issues/1511
                var methodsUsedAsDelegates = PooledConcurrentSet <IMethodSymbol> .GetInstance();

                symbolStartContext.RegisterOperationAction(OnMethodReference, OperationKind.MethodReference);
                symbolStartContext.RegisterOperationBlockStartAction(OnOperationBlockStart);
                symbolStartContext.RegisterSymbolEndAction(OnSymbolEnd);

                return;

                void OnMethodReference(OperationAnalysisContext operationContext)
                {
                    var methodReference = (IMethodReferenceOperation)operationContext.Operation;

                    methodsUsedAsDelegates.Add(methodReference.Method);
                }

                void OnOperationBlockStart(OperationBlockStartAnalysisContext blockStartContext)
                {
#pragma warning disable IDE0083 // Use pattern matching - need new compiler
                    if (!(blockStartContext.OwningSymbol is IMethodSymbol methodSymbol))
#pragma warning restore IDE0083 // Use pattern matching
                    {
                        return;
                    }

                    // Don't run any other check for this method if it isn't a valid analysis context
                    if (!ShouldAnalyze(methodSymbol, wellKnownTypeProvider, skippedAttributes,
                                       blockStartContext.Options, isWebProject, blockStartContext.CancellationToken))
                    {
                        return;
                    }

                    // Don't report methods which have a single throw statement
                    // with NotImplementedException or NotSupportedException
                    if (blockStartContext.IsMethodNotImplementedOrSupported())
                    {
                        return;
                    }

                    bool isInstanceReferenced = false;

                    blockStartContext.RegisterOperationAction(operationContext =>
                    {
                        if (((IInstanceReferenceOperation)operationContext.Operation).ReferenceKind == InstanceReferenceKind.ContainingTypeInstance)
                        {
                            isInstanceReferenced = true;
                        }
                    }, OperationKind.InstanceReference);

                    blockStartContext.RegisterOperationBlockEndAction(blockEndContext =>
                    {
                        if (!isInstanceReferenced)
                        {
                            if (methodSymbol.IsAccessorMethod())
                            {
                                accessorCandidates.Add(methodSymbol);
                                propertyOrEventCandidates.Add(methodSymbol.AssociatedSymbol);
                            }
                            else if (methodSymbol.IsExternallyVisible())
                            {
                                if (!IsOnObsoleteMemberChain(methodSymbol, wellKnownTypeProvider))
                                {
                                    blockEndContext.ReportDiagnostic(methodSymbol.CreateDiagnostic(Rule, methodSymbol.Name));
                                }
                            }
                            else
                            {
                                methodCandidates.Add(methodSymbol);
                            }
                        }
                    });
                }

                void OnSymbolEnd(SymbolAnalysisContext symbolEndContext)
                {
                    foreach (var candidate in methodCandidates)
                    {
                        if (methodsUsedAsDelegates.Contains(candidate))
                        {
                            continue;
                        }

                        if (!IsOnObsoleteMemberChain(candidate, wellKnownTypeProvider))
                        {
                            symbolEndContext.ReportDiagnostic(candidate.CreateDiagnostic(Rule, candidate.Name));
                        }
                    }

                    foreach (var candidatePropertyOrEvent in propertyOrEventCandidates)
                    {
                        var allAccessorsAreCandidates = true;
                        foreach (var accessor in candidatePropertyOrEvent.GetAccessors())
                        {
                            if (!accessorCandidates.Contains(accessor) ||
                                IsOnObsoleteMemberChain(accessor, wellKnownTypeProvider))
                            {
                                allAccessorsAreCandidates = false;
                                break;
                            }
                        }

                        if (allAccessorsAreCandidates)
                        {
                            symbolEndContext.ReportDiagnostic(candidatePropertyOrEvent.CreateDiagnostic(Rule, candidatePropertyOrEvent.Name));
                        }
                    }

                    propertyOrEventCandidates.Free(symbolEndContext.CancellationToken);
                    accessorCandidates.Free(symbolEndContext.CancellationToken);
                    methodCandidates.Free(symbolEndContext.CancellationToken);
                    methodsUsedAsDelegates.Free(symbolEndContext.CancellationToken);
                }
            }
Пример #11
0
 // Actions/Symbol
 private static void OnSymbol_Start(SymbolStartAnalysisContext context)
 {
     context.RegisterSymbolEndAction(OnSymbol_End);
 }