示例#1
0
            private void RegisterActions(CompilationStartAnalysisContext compilationStartContext)
            {
                // We register following actions in the compilation:
                // 1. A symbol action for member symbols to ensure the member's unused state is initialized to true for every private member symbol.
                // 2. Operation actions for member references, invocations and object creations to detect member usages, i.e. read or read reference taken.
                // 3. Operation action for field initializers to detect non-constant initialization.
                // 4. Operation action for invalid operations to bail out on erroneous code.
                // 5. A symbol start/end action for named types to report diagnostics for candidate members that have no usage in executable code.
                //
                // Note that we need to register separately for OperationKind.Invocation and OperationKind.ObjectCreation due to https://github.com/dotnet/roslyn/issues/26206

                compilationStartContext.RegisterSymbolAction(AnalyzeSymbolDeclaration, SymbolKind.Method, SymbolKind.Field, SymbolKind.Property, SymbolKind.Event);

                Action <ISymbol, ValueUsageInfo> onSymbolUsageFound = OnSymbolUsage;

                compilationStartContext.RegisterSymbolStartAction(symbolStartContext =>
                {
                    var hasInvalidOrDynamicOperation = false;
                    symbolStartContext.RegisterOperationAction(AnalyzeMemberReferenceOperation, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.EventReference);
                    symbolStartContext.RegisterOperationAction(AnalyzeFieldInitializer, OperationKind.FieldInitializer);
                    symbolStartContext.RegisterOperationAction(AnalyzeInvocationOperation, OperationKind.Invocation);
                    symbolStartContext.RegisterOperationAction(AnalyzeNameOfOperation, OperationKind.NameOf);
                    symbolStartContext.RegisterOperationAction(AnalyzeObjectCreationOperation, OperationKind.ObjectCreation);
                    symbolStartContext.RegisterOperationAction(_ => hasInvalidOrDynamicOperation = true, OperationKind.Invalid,
                                                               OperationKind.DynamicIndexerAccess, OperationKind.DynamicInvocation, OperationKind.DynamicMemberReference, OperationKind.DynamicObjectCreation);
                    symbolStartContext.RegisterSymbolEndAction(symbolEndContext => OnSymbolEnd(symbolEndContext, hasInvalidOrDynamicOperation));

                    // Register custom language-specific actions, if any.
                    _analyzer.HandleNamedTypeSymbolStart(symbolStartContext, onSymbolUsageFound);
                }, SymbolKind.NamedType);
            }
示例#2
0
            private void RegisterActions(CompilationStartAnalysisContext compilationStartContext)
            {
                // We register following actions in the compilation:
                // 1. A symbol action for member symbols to ensure the member's unused state is initialized to true for every private member symbol.
                // 2. Operation actions for member references, invocations and object creations to detect member usages, i.e. read or read reference taken.
                // 3. Operation action for field initializers to detect non-constant initialization.
                // 4. Operation action for invalid operations to bail out on erroneous code.
                // 5. A symbol start/end action for named types to report diagnostics for candidate members that have no usage in executable code.
                //
                // Note that we need to register separately for OperationKind.Invocation and OperationKind.ObjectCreation due to https://github.com/dotnet/roslyn/issues/26206

                compilationStartContext.RegisterSymbolAction(AnalyzeSymbolDeclaration, SymbolKind.Method, SymbolKind.Field, SymbolKind.Property, SymbolKind.Event);

                Action <ISymbol, ValueUsageInfo> onSymbolUsageFound = OnSymbolUsage;

                compilationStartContext.RegisterSymbolStartAction(symbolStartContext =>
                {
                    var hasUnsupportedOperation = false;
                    symbolStartContext.RegisterOperationAction(AnalyzeMemberReferenceOperation, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.EventReference);
                    symbolStartContext.RegisterOperationAction(AnalyzeFieldInitializer, OperationKind.FieldInitializer);
                    symbolStartContext.RegisterOperationAction(AnalyzeInvocationOperation, OperationKind.Invocation);
                    symbolStartContext.RegisterOperationAction(AnalyzeNameOfOperation, OperationKind.NameOf);
                    symbolStartContext.RegisterOperationAction(AnalyzeObjectCreationOperation, OperationKind.ObjectCreation);

                    // We bail out reporting diagnostics for named types if it contains following kind of operations:
                    //  1. Invalid operations, i.e. erroneous code:
                    //     We do so to ensure that we don't report false positives during editing scenarios in the IDE, where the user
                    //     is still editing code and fixing unresolved references to symbols, such as overload resolution errors.
                    //  2. Dynamic operations, where we do not know the exact member being referenced at compile time.
                    //  3. Operations with OperationKind.None which are not operation root nodes. Attributes
                    //     generate operation blocks with root operation with OperationKind.None, and we don't want to bail out for them.
                    symbolStartContext.RegisterOperationAction(_ => hasUnsupportedOperation = true, OperationKind.Invalid,
                                                               OperationKind.DynamicIndexerAccess, OperationKind.DynamicInvocation, OperationKind.DynamicMemberReference, OperationKind.DynamicObjectCreation);
                    symbolStartContext.RegisterOperationAction(AnalyzeOperationNone, OperationKind.None);

                    symbolStartContext.RegisterSymbolEndAction(symbolEndContext => OnSymbolEnd(symbolEndContext, hasUnsupportedOperation));

                    // Register custom language-specific actions, if any.
                    _analyzer.HandleNamedTypeSymbolStart(symbolStartContext, onSymbolUsageFound);

                    return;

                    void AnalyzeOperationNone(OperationAnalysisContext context)
                    {
                        if (context.Operation.Kind == OperationKind.None &&
                            context.Operation.Parent != null)
                        {
                            hasUnsupportedOperation = true;
                        }
                    }
                }, SymbolKind.NamedType);
            }