private bool ValidateExpression(IExpressionStatementOperation expressionStatement) { if (expressionStatement.Operation?.Kind != OperationKind.Invocation) { return(false); } var invocation = (IInvocationOperation)expressionStatement.Operation; // Valid calls are either to Dispose(false), or to the Finalize method of the base type if (!_callDispose) { bool result = IsDisposeBoolCall(invocation, _type, expectedValue: false); if (result) { _callDispose = true; } return(result); } else if (_type.BaseType != null && invocation.Instance != null && invocation.Instance.Kind == OperationKind.InstanceReference) { IMethodSymbol methodSymbol = invocation.TargetMethod; IInstanceReferenceOperation receiver = (IInstanceReferenceOperation)invocation.Instance; return(methodSymbol.IsFinalizer() && Equals(receiver.Type.OriginalDefinition, _type.BaseType.OriginalDefinition)); } return(false); }
private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation) { // Modifiers that we don't care about if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual || methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember()) { return(false); } if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer()) { return(false); } // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases. if (methodSymbol.ContainingType.IsGenericType && methodSymbol.IsExternallyVisible()) { return(false); } // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same. var skipAttributes = new[] { "WebMethodAttribute", "TestInitializeAttribute", "TestMethodAttribute", "TestCleanupAttribute", }; if (methodSymbol.GetAttributes().Any(attribute => skipAttributes.Contains(attribute.AttributeClass.Name))) { return(false); } // If this looks like an event handler don't flag such cases. if (methodSymbol.Parameters.Length == 2 && methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object && IsEventArgs(methodSymbol.Parameters[1].Type, compilation)) { return(false); } if (IsExplicitlyVisibleFromCom(methodSymbol, compilation)) { return(false); } return(true); }
private static bool IsSkippedMethod(IMethodSymbol methodSymbol, WellKnownTypeProvider wellKnownTypeProvider) { if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer()) { return(true); } if (methodSymbol.ReturnsVoid && methodSymbol.Parameters.IsEmpty && (methodSymbol.Name == "Application_Start" || methodSymbol.Name == "Application_End") && methodSymbol.ContainingType.Inherits(wellKnownTypeProvider.GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemWebHttpApplication))) { return(true); } return(false); }
private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation, ImmutableArray <INamedTypeSymbol> skippedAttributes) { // Modifiers that we don't care about if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual || methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember()) { return(false); } if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer()) { return(false); } // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases. if (methodSymbol.ContainingType.IsGenericType && methodSymbol.IsExternallyVisible()) { return(false); } // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same. if (methodSymbol.GetAttributes().Any(attribute => skippedAttributes.Any(attr => attribute.AttributeClass.Inherits(attr)))) { return(false); } // If this looks like an event handler don't flag such cases. // However, we do want to consider EventRaise accessor as a candidate // so we can flag the associated event if none of it's accessors need instance reference. if (methodSymbol.Parameters.Length == 2 && methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object && IsEventArgs(methodSymbol.Parameters[1].Type, compilation) && methodSymbol.MethodKind != MethodKind.EventRaise) { return(false); } if (IsExplicitlyVisibleFromCom(methodSymbol, compilation)) { return(false); } return(true); }
#pragma warning disable RS1012 // Start action has no registered actions. private static bool ShouldAnalyzeMethod( IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, INamedTypeSymbol?eventsArgSymbol, ImmutableHashSet <INamedTypeSymbol?> attributeSetForMethodsToIgnore, INamedTypeSymbol?serializationInfoType, INamedTypeSymbol?streamingContextType) #pragma warning restore RS1012 // Start action has no registered actions. { // We only care about methods with parameters. if (method.Parameters.IsEmpty) { return(false); } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return(false); } // Ignore property accessors. if (method.IsPropertyAccessor()) { return(false); } // Ignore serialization special methods if (method.IsSerializationConstructor(serializationInfoType, streamingContextType) || method.IsGetObjectData(serializationInfoType, streamingContextType)) { return(false); } // Ignore event handler methods "Handler(object, MyEventArgs)" if (method.HasEventHandlerSignature(eventsArgSymbol)) { return(false); } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return(false); } // Bail out if user has configured to skip analysis for the method. if (!method.MatchesConfiguredVisibility( startOperationBlockContext.Options, Rule, startOperationBlockContext.Compilation, startOperationBlockContext.CancellationToken, defaultRequiredVisibility: SymbolVisibilityGroup.All)) { return(false); } // Check to see if the method just throws a NotImplementedException/NotSupportedException // We shouldn't warn about parameters in that case if (startOperationBlockContext.IsMethodNotImplementedOrSupported()) { return(false); } return(true); }
private static bool IsFinalizer(IMethodSymbol method, Compilation compilation) { return(method.IsFinalizer()); }
private static void AnalyzeMethod( IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, UnusedParameterDictionary unusedMethodParameters, INamedTypeSymbol eventsArgSymbol, ISet <IMethodSymbol> methodsUsedAsDelegates, ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore) { // We only care about methods with parameters. if (method.Parameters.IsEmpty) { return; } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return; } // Ignore property accessors. if (method.IsPropertyAccessor()) { return; } // Ignore event handler methods "Handler(object, MyEventArgs)" if (eventsArgSymbol != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.Inherits(eventsArgSymbol)) { return; } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return; } // Ignore methods that were used as delegates if (methodsUsedAsDelegates.Contains(method)) { return; } // Initialize local mutable state in the start action. var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters); // Register an intermediate non-end action that accesses and modifies the state. startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeParameterReference, OperationKind.ParameterReference); // Register an end action to add unused parameters to the unusedMethodParameters dictionary startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction); }
private static void AnalyzeMethod( IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, UnusedParameterDictionary unusedMethodParameters, INamedTypeSymbol?eventsArgSymbol, ISet <IMethodSymbol> methodsUsedAsDelegates, ImmutableHashSet <INamedTypeSymbol?> attributeSetForMethodsToIgnore) { // We only care about methods with parameters. if (method.Parameters.IsEmpty) { return; } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return; } // Ignore property accessors. if (method.IsPropertyAccessor()) { return; } // Ignore event handler methods "Handler(object, MyEventArgs)" if (method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && // UWP has specific EventArgs not inheriting from System.EventArgs. It was decided to go for a suffix match rather than a whitelist. (method.Parameters[1].Type.Inherits(eventsArgSymbol) || method.Parameters[1].Type.Name.EndsWith("EventArgs", StringComparison.Ordinal))) { return; } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return; } // Ignore methods that were used as delegates if (methodsUsedAsDelegates.Contains(method)) { return; } // Bail out if user has configured to skip analysis for the method. if (!method.MatchesConfiguredVisibility( startOperationBlockContext.Options, Rule, startOperationBlockContext.CancellationToken, defaultRequiredVisibility: SymbolVisibilityGroup.All)) { return; } // Initialize local mutable state in the start action. var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters); // Register an intermediate non-end action that accesses and modifies the state. startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeParameterReference, OperationKind.ParameterReference); // Register an end action to add unused parameters to the unusedMethodParameters dictionary startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction); }
#pragma warning disable RS1012 // Start action has no registered actions. private static bool ShouldAnalyzeMethod( IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, INamedTypeSymbol?eventsArgSymbol, ImmutableHashSet <INamedTypeSymbol?> attributeSetForMethodsToIgnore) #pragma warning restore RS1012 // Start action has no registered actions. { // We only care about methods with parameters. if (method.Parameters.IsEmpty) { return(false); } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return(false); } // Ignore property accessors. if (method.IsPropertyAccessor()) { return(false); } // Ignore event handler methods "Handler(object, MyEventArgs)" if (method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && // UWP has specific EventArgs not inheriting from System.EventArgs. It was decided to go for a suffix match rather than a whitelist. (method.Parameters[1].Type.Inherits(eventsArgSymbol) || method.Parameters[1].Type.Name.EndsWith("EventArgs", StringComparison.Ordinal))) { return(false); } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return(false); } // Bail out if user has configured to skip analysis for the method. if (!method.MatchesConfiguredVisibility( startOperationBlockContext.Options, Rule, startOperationBlockContext.CancellationToken, defaultRequiredVisibility: SymbolVisibilityGroup.All)) { return(false); } // Check to see if the method just throws a NotImplementedException/NotSupportedException // We shouldn't warn about parameters in that case if (startOperationBlockContext.IsMethodNotImplementedOrSupported()) { return(false); } return(true); }
private static bool ShouldAnalyze(IMethodSymbol methodSymbol, Compilation compilation) { // Modifiers that we don't care about if (methodSymbol.IsStatic || methodSymbol.IsOverride || methodSymbol.IsVirtual || methodSymbol.IsExtern || methodSymbol.IsAbstract || methodSymbol.IsImplementationOfAnyInterfaceMember()) { return false; } if (methodSymbol.IsConstructor() || methodSymbol.IsFinalizer()) { return false; } // CA1000 says one shouldn't declare static members on generic types. So don't flag such cases. if (methodSymbol.ContainingType.IsGenericType && methodSymbol.GetResultantVisibility() == SymbolVisibility.Public) { return false; } // FxCop doesn't check for the fully qualified name for these attributes - so we'll do the same. var skipAttributes = new[] { "WebMethodAttribute", "TestInitializeAttribute", "TestMethodAttribute", "TestCleanupAttribute", }; if (methodSymbol.GetAttributes().Any(attribute => skipAttributes.Contains(attribute.AttributeClass.Name))) { return false; } // If this looks like an event handler don't flag such cases. if (methodSymbol.Parameters.Length == 2 && methodSymbol.Parameters[0].Type.SpecialType == SpecialType.System_Object && IsEventArgs(methodSymbol.Parameters[1].Type, compilation)) { return false; } if (IsExplicitlyVisibleFromCom(methodSymbol, compilation)) { return false; } return true; }
private static bool IsFinalizer(IMethodSymbol method, Compilation compilation) { return method.IsFinalizer(); }