private static bool IsAddedToFieldOrProperty(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooledInvocations = InvocationWalker.Create(block)) { foreach (var invocation in pooledInvocations.Item.Invocations) { var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (method?.Name == "Add") { using (var pooledIdentifiers = IdentifierNameWalker.Create(invocation.ArgumentList)) { foreach (var identifierName in pooledIdentifiers.Item.IdentifierNames) { var argSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken); if (symbol.Equals(argSymbol)) { return(true); } } } } } } return(false); }
private static void HandleDisposeMethod(SyntaxNodeAnalysisContext context) { if (context.IsExcludedFromAnalysis()) { return; } if (context.ContainingSymbol is IMethodSymbol method && method.IsOverride && method.Name == "Dispose") { var overridden = method.OverriddenMethod; if (overridden == null) { return; } using (var invocations = InvocationWalker.Create(context.Node)) { foreach (var invocation in invocations.Item) { if ( SymbolComparer.Equals( context.SemanticModel.GetSymbolSafe(invocation, context.CancellationToken), overridden)) { return; } } } if (overridden.DeclaringSyntaxReferences.Length == 0) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation())); return; } using ( var disposeWalker = Disposable.DisposeWalker.Create(overridden, context.SemanticModel, context.CancellationToken)) { foreach (var disposeCall in disposeWalker.Item) { if (Disposable.TryGetDisposedRootMember(disposeCall, context.SemanticModel, context.CancellationToken, out ExpressionSyntax disposed)) { var member = context.SemanticModel.GetSymbolSafe(disposed, context.CancellationToken); if ( !Disposable.IsMemberDisposed(member, method, context.SemanticModel, context.CancellationToken)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation())); return; } } } } } }
private static bool IsDisposedAfter(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooled = InvocationWalker.Create(assignment.FirstAncestorOrSelf <MemberDeclarationSyntax>())) { foreach (var invocation in pooled.Item.Invocations) { if (!IsAfter(invocation, assignment)) { continue; } if (Disposable.IsDisposing(invocation, symbol, semanticModel, cancellationToken)) { return(true); } } } return(false); }
private static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooled = InvocationWalker.Create(assignment.FirstAncestorOrSelf <MemberDeclarationSyntax>())) { foreach (var invocation in pooled.Item.Invocations) { if (invocation.IsBeforeInScope(assignment) != Result.Yes) { continue; } var invokedSymbol = semanticModel.GetSymbolSafe(invocation, cancellationToken); if (invokedSymbol?.Name != "Dispose") { continue; } var statement = invocation.FirstAncestorOrSelf <StatementSyntax>(); if (statement != null) { using (var pooledNames = IdentifierNameWalker.Create(statement)) { foreach (var identifierName in pooledNames.Item.IdentifierNames) { var otherSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken); if (symbol.Equals(otherSymbol)) { return(true); } } } } } } return(false); }
private static bool IsReturned(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooled = ReturnValueWalker.Create(block, Search.TopLevel, semanticModel, cancellationToken)) { foreach (var value in pooled.Item) { var returnedSymbol = semanticModel.GetSymbolSafe(value, cancellationToken); if (SymbolComparer.Equals(symbol, returnedSymbol)) { return(true); } if (value is ObjectCreationExpressionSyntax objectCreation) { if (objectCreation.ArgumentList != null) { foreach (var argument in objectCreation.ArgumentList.Arguments) { var arg = semanticModel.GetSymbolSafe(argument.Expression, cancellationToken); if (SymbolComparer.Equals(symbol, arg)) { return(true); } } } if (objectCreation.Initializer != null) { foreach (var argument in objectCreation.Initializer.Expressions) { var arg = semanticModel.GetSymbolSafe(argument, cancellationToken); if (SymbolComparer.Equals(symbol, arg)) { return(true); } } } } if (value is InvocationExpressionSyntax invocation) { if (returnedSymbol == KnownSymbol.RxDisposable.Create && invocation.ArgumentList != null && invocation.ArgumentList.Arguments.TryGetSingle(out ArgumentSyntax argument)) { var body = (argument.Expression as ParenthesizedLambdaExpressionSyntax)?.Body; using (var pooledInvocations = InvocationWalker.Create(body)) { foreach (var candidate in pooledInvocations.Item.Invocations) { if (Disposable.IsDisposing(candidate, symbol, semanticModel, cancellationToken)) { return(true); } } } } } } } return(false); }