private static void AnalyzeNodeWithinLocalDeclaration(CustomAnalysisContext context, string localVariableName) { if (!context.Node.TryFindParentScope(out var parentScope)) { return; } var localVariableInsideUsing = parentScope .DescendantNodes <UsingStatementSyntax>() .SelectMany(@using => @using.DescendantNodes <IdentifierNameSyntax>()) .Where(id => localVariableName != null && (string)id.Identifier.Value == localVariableName) .ToArray(); if (localVariableInsideUsing.Any()) { if (localVariableInsideUsing.Any(id => id.Parent is UsingStatementSyntax)) //using(mem)) { return; } if (IsArgumentInConstructorOfTrackingTypeWithinUsing(context, localVariableInsideUsing)) { return; } context.ReportNotDisposedLocalVariable(); return; } var invocationExpressions = parentScope.DescendantNodes <InvocationExpressionSyntax>().ToArray(); if (invocationExpressions.Any(ie => ie.IsInterlockedExchangeAssignExpressionFor(localVariableName))) { return; } if (ExistsDisposeCall(localVariableName, invocationExpressions, context.SemanticModel)) { return; } if (IsArgumentInTrackingMethod(context, localVariableName, invocationExpressions)) { return; } if (IsArgumentInConstructorOfTrackingType(context, localVariableName, parentScope)) { return; } if (IsCallToMethodThatIsConsideredAsDisposeCall(invocationExpressions, context)) { return; } context.ReportNotDisposedLocalVariable(); }
private static void AnalyzeInvocationExpressionInsideAwaitExpression(CustomAnalysisContext context) { var node = context.Node; var awaitExpression = node.Parent as AwaitExpressionSyntax; var awaitExpressionInfo = context.SemanticModel.GetAwaitExpressionInfo(awaitExpression); if (!(awaitExpressionInfo.GetResultMethod?.ReturnType is INamedTypeSymbol returnType)) { return; } if (!returnType.IsDisposableOrImplementsDisposable()) { return; } if (Detector.IsIgnoredTypeOrImplementsIgnoredInterface(returnType)) { return; } if (awaitExpression.IsDescendantOfUsingHeader()) { return; } if (awaitExpression.IsPartOfVariableDeclaratorInsideAUsingDeclaration()) { return; } if (awaitExpression.IsPartOfReturnStatementInMethod()) { return; } if (awaitExpression.IsReturnedLaterWithinMethod()) { return; } if (awaitExpression.IsDescendantOfVariableDeclarator()) { AnalyzeNodeWithinVariableDeclarator(context.NewWith(awaitExpression)); } else if (awaitExpression.IsDescendantOfAssignmentExpressionSyntax()) { if (node.TryFindParentClass(out var @class)) { var assignment = awaitExpression?.Parent as AssignmentExpressionSyntax; var member = (assignment?.Left as IdentifierNameSyntax)?.Identifier.Text; var isDisposed = @class.ContainsDisposeCallFor(member, context.SemanticModel, Configuration); if (isDisposed) { return; } } context.ReportNotDisposedLocalVariable(); } else { context.ReportNotDisposedAnonymousObject(); } }
private static void AnalyzeNodeInAssignmentExpression(CustomAnalysisContext context) { var node = context.Node; //is local or global variable var assignmentExpressionSyntax = node.Parent as AssignmentExpressionSyntax; var variableName = (assignmentExpressionSyntax?.Left as IdentifierNameSyntax)?.Identifier.Text; if (node.TryFindContainingMethod(out var containingMethod)) { if (containingMethod.ContainsDisposeCallFor(variableName, context.SemanticModel, Configuration)) { return; } if (containingMethod.HasDecendentVariableDeclaratorFor(variableName)) { //local declaration in method if (containingMethod.Returns(variableName)) { return; } if (node.IsDescendantOfUsingHeader()) { return; } if (node.IsArgumentInObjectCreation()) { AnalyzeNodeInArgumentList(context); return; } if (containingMethod.HasInterlockedExchangeWith(variableName)) { return; } //is part of tracking call context.ReportNotDisposedLocalVariable(); return; } if (node.IsDisposedInDisposingMethod(variableName, Configuration, context.SemanticModel)) { return; } if (node.IsArgumentInObjectCreation()) { AnalyzeNodeInArgumentList(context); return; } //assignment to field or property ReportStaticOrNonStaticNotDisposedMember(context, variableName); return; } if (node.TryFindContainingCtor(out var ctor)) { if (ctor.HasDecendentVariableDeclaratorFor(variableName)) { //local variable in ctor if (ctor.HasInterlockedExchangeWith(variableName)) { return; } if (node.IsDescendantOfUsingHeader()) { return; } if (node.IsArgumentInObjectCreation()) { AnalyzeNodeInArgumentList(context); return; } if (ctor.ContainsDisposeCallFor(variableName, context.SemanticModel, Configuration)) { return; } context.ReportNotDisposedLocalVariable(); } else //field or property { if (node.IsDisposedInDisposingMethod(variableName, Configuration, context.SemanticModel)) { return; } if (node.IsAssignmentToProperty(variableName, out var isStatic)) { if (isStatic) { context.ReportNotDisposedStaticProperty(variableName); } else { context.ReportNotDisposedProperty(variableName); } } else { if (node.IsAssignmentToStaticField(variableName)) { context.ReportNotDisposedStaticField(variableName); } else { context.ReportNotDisposedField(variableName); } } } } }