예제 #1
0
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(
                compilationStartAnalysisContext =>
            {
                Compilation compilation = compilationStartAnalysisContext.Compilation;

                ImmutableHashSet <INamedTypeSymbol> nativeResourceTypes = ImmutableHashSet.Create(
                    WellKnownTypes.IntPtr(compilation),
                    WellKnownTypes.UIntPtr(compilation),
                    WellKnownTypes.HandleRef(compilation)
                    );
                var disposableType = WellKnownTypes.IDisposable(compilation);

                compilationStartAnalysisContext.RegisterOperationAction(
                    operationAnalysisContext =>
                {
                    var assignment = (IAssignmentOperation)operationAnalysisContext.Operation;

                    IOperation target = assignment.Target;
                    if (target == null)
                    {
                        // This can happen if the left-hand side is an undefined symbol.
                        return;
                    }

                    if (target.Kind != OperationKind.FieldReference)
                    {
                        return;
                    }

                    var fieldReference = (IFieldReferenceOperation)target;
                    var field          = fieldReference.Member as IFieldSymbol;
                    if (field == null || field.Kind != SymbolKind.Field || field.IsStatic)
                    {
                        return;
                    }

                    if (!nativeResourceTypes.Contains(field.Type))
                    {
                        return;
                    }

                    INamedTypeSymbol containingType = field.ContainingType;
                    if (containingType == null || containingType.IsValueType)
                    {
                        return;
                    }

                    if (!containingType.AllInterfaces.Contains(disposableType))
                    {
                        return;
                    }

                    if (containingType.HasFinalizer())
                    {
                        return;
                    }

                    if (assignment.Value == null || assignment.Value.Kind != OperationKind.Invocation)
                    {
                        return;
                    }

                    var invocation = (IInvocationOperation)assignment.Value;
                    if (invocation == null)
                    {
                        return;
                    }

                    IMethodSymbol method = invocation.TargetMethod;

                    // TODO: What about COM?
                    if (method.GetDllImportData() == null)
                    {
                        return;
                    }

                    operationAnalysisContext.ReportDiagnostic(containingType.CreateDiagnostic(Rule));
                },
                    OperationKind.SimpleAssignment);
            });
        }