private static bool IsAddedToFieldOrProperty(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooledInvocations = InvocationWalker.Borrow(block)) { foreach (var invocation in pooledInvocations.Invocations) { var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (method?.Name == "Add") { using (var nameWalker = IdentifierNameWalker.Borrow(invocation.ArgumentList)) { foreach (var identifierName in nameWalker.IdentifierNames) { var argSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken); if (symbol.Equals(argSymbol)) { return(true); } } } } } } return(false); }
internal static bool IsMemberDisposed(ISymbol member, IMethodSymbol disposeMethod, SemanticModel semanticModel, CancellationToken cancellationToken) { if (member == null || disposeMethod == null) { return(false); } foreach (var reference in disposeMethod.DeclaringSyntaxReferences) { var node = reference.GetSyntax(cancellationToken) as MethodDeclarationSyntax; using (var pooled = DisposeWalker.Borrow(disposeMethod, semanticModel, cancellationToken)) { foreach (var invocation in pooled) { if (IsDisposing(invocation, member, semanticModel, cancellationToken)) { return(true); } } } using (var walker = IdentifierNameWalker.Borrow(node)) { foreach (var identifier in walker.IdentifierNames) { var memberAccess = identifier.Parent as MemberAccessExpressionSyntax; if (memberAccess?.Expression is BaseExpressionSyntax) { var baseMethod = semanticModel.GetSymbolSafe(identifier, cancellationToken) as IMethodSymbol; if (baseMethod?.Name == "Dispose") { if (IsMemberDisposed(member, baseMethod, semanticModel, cancellationToken)) { return(true); } } } if (identifier.Identifier.ValueText != member.Name) { continue; } var symbol = semanticModel.GetSymbolSafe(identifier, cancellationToken); if (member.Equals(symbol) || (member as IPropertySymbol)?.OverriddenProperty?.Equals(symbol) == true) { return(true); } } } } return(false); }
private static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooled = InvocationWalker.Borrow(assignment.FirstAncestorOrSelf <MemberDeclarationSyntax>())) { foreach (var invocation in pooled.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 names = IdentifierNameWalker.Borrow(statement)) { foreach (var identifierName in names.IdentifierNames) { var otherSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken); if (symbol.Equals(otherSymbol)) { return(true); } } } } } } return(false); }
internal static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken) { bool IsDisposing(InvocationExpressionSyntax invocation, ISymbol current) { if (invocation.TryGetInvokedMethodName(out var name) && name != "Dispose") { return(false); } var invokedSymbol = semanticModel.GetSymbolSafe(invocation, cancellationToken); if (invokedSymbol?.Name != "Dispose") { return(false); } var statement = invocation.FirstAncestorOrSelf <StatementSyntax>(); if (statement != null) { using (var names = IdentifierNameWalker.Borrow(statement)) { foreach (var identifierName in names.IdentifierNames) { if (identifierName.Identifier.ValueText == current.Name && SymbolComparer.Equals(current, semanticModel.GetSymbolSafe(identifierName, cancellationToken))) { return(true); } } } } return(false); } bool TryGetScope(SyntaxNode node, out BlockSyntax result) { result = null; if (node.FirstAncestor <AnonymousFunctionExpressionSyntax>() is AnonymousFunctionExpressionSyntax lambda) { result = lambda.Body as BlockSyntax; } else if (node.FirstAncestor <AccessorDeclarationSyntax>() is AccessorDeclarationSyntax accessor) { result = accessor.Body; } else if (node.FirstAncestor <BaseMethodDeclarationSyntax>() is BaseMethodDeclarationSyntax method) { result = method.Body; } return(result != null); } if (TryGetScope(assignment, out var block)) { using (var walker = InvocationWalker.Borrow(block)) { foreach (var invocation in walker.Invocations) { if (invocation.IsBeforeInScope(assignment) != Result.Yes) { continue; } if (IsDisposing(invocation, symbol)) { return(true); } } } } if (assignment is AssignmentExpressionSyntax assignmentExpression && semanticModel.GetSymbolSafe(assignmentExpression.Left, cancellationToken) is IPropertySymbol property && property.TryGetSetter(cancellationToken, out var setter)) { using (var pooled = InvocationWalker.Borrow(setter)) { foreach (var invocation in pooled.Invocations) { if (IsDisposing(invocation, symbol) || IsDisposing(invocation, property)) { return(true); } } } } return(false); }
private static bool IsUsedAfter(ILocalSymbol local, InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out IReadOnlyList <Location> locations) { if (local.TrySingleDeclaration(context.CancellationToken, out var declaration) && declaration.TryFirstAncestor(out BlockSyntax block)) { List <Location> temp = null; using (var walker = IdentifierNameWalker.Borrow(block)) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.Identifier.ValueText == local.Name && invocation.IsExecutedBefore(identifierName) == ExecutedBefore.Yes && context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ILocalSymbol candidate) && local.Equals(candidate) && !IsAssigned(identifierName) && !IsReassigned(identifierName)) { if (temp == null) { temp = new List <Location>(); } temp.Add(identifierName.GetLocation()); } } locations = temp; return(locations != null); } } locations = null; return(false); bool IsAssigned(IdentifierNameSyntax identifier) { switch (identifier.Parent) { case AssignmentExpressionSyntax assignment: return(assignment.Left == identifier); case ArgumentSyntax argument when argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword): return(true); } return(false); } bool IsReassigned(ExpressionSyntax location) { using (var walker = MutationWalker.For(local, context.SemanticModel, context.CancellationToken)) { foreach (var mutation in walker.All()) { if (mutation.TryFirstAncestorOrSelf(out ExpressionSyntax expression) && invocation.IsExecutedBefore(expression) != ExecutedBefore.No && expression.IsExecutedBefore(location) != ExecutedBefore.No) { return(true); } } } return(false); } }