internal static bool IsAssignedAndDisposedInSetupAndTearDown(ISymbol fieldOrProperty, TypeDeclarationSyntax scope, SemanticModel semanticModel, CancellationToken cancellationToken) { if (fieldOrProperty == null) { return(false); } if (AssignmentWalker.SingleForSymbol(fieldOrProperty, scope, Search.TopLevel, semanticModel, cancellationToken, out var assignment) && assignment.FirstAncestor <MethodDeclarationSyntax>() is MethodDeclarationSyntax methodDeclaration) { if (Attribute.TryGetAttribute(methodDeclaration, KnownSymbol.NUnitSetUpAttribute, semanticModel, cancellationToken, out _)) { if (fieldOrProperty.ContainingType.TryFirstMethodRecursive( x => x.GetAttributes().Any(a => a.AttributeClass == KnownSymbol.NUnitTearDownAttribute), out var tearDown)) { return(RefCounter.IsMemberDisposed(fieldOrProperty, tearDown, semanticModel, cancellationToken)); } } if (Attribute.TryGetAttribute(methodDeclaration, KnownSymbol.NUnitOneTimeSetUpAttribute, semanticModel, cancellationToken, out _)) { if (fieldOrProperty.ContainingType.TryFirstMethodRecursive( x => x.GetAttributes().Any(a => a.AttributeClass == KnownSymbol.NUnitOneTimeTearDownAttribute), out var tearDown)) { return(RefCounter.IsMemberDisposed(fieldOrProperty, tearDown, semanticModel, cancellationToken)); } } } return(false); }
internal static bool TryGetAssignment(this BlockSyntax body, ISymbol symbol, SemanticModel semanticModel, CancellationToken cancellationToken, List <AssignmentExpressionSyntax> result) { if (symbol == null) { return(false); } AssignmentWalker.AllWith(symbol, body, Search.TopLevel, semanticModel, cancellationToken, result); return(true); }
internal static bool TryGetAssignment(this BlockSyntax body, ISymbol symbol, SemanticModel semanticModel, CancellationToken cancellationToken, out AssignmentExpressionSyntax result) { result = null; if (symbol == null) { return(false); } return(AssignmentWalker.FirstWith(symbol, body, Search.TopLevel, semanticModel, cancellationToken, out result)); }
internal static bool IsAssignedInSetUp(ISymbol fieldOrProperty, TypeDeclarationSyntax scope, SemanticModel semanticModel, CancellationToken cancellationToken, out AttributeSyntax attribute) { if (AssignmentWalker.SingleForSymbol(fieldOrProperty, scope, Search.TopLevel, semanticModel, cancellationToken, out var assignment) && assignment.FirstAncestor <MethodDeclarationSyntax>() is MethodDeclarationSyntax methodDeclaration) { return(Attribute.TryGetAttribute(methodDeclaration, KnownSymbol.NUnitSetUpAttribute, semanticModel, cancellationToken, out attribute) || Attribute.TryGetAttribute(methodDeclaration, KnownSymbol.NUnitOneTimeSetUpAttribute, semanticModel, cancellationToken, out attribute)); } attribute = null; return(false); }
internal static bool AssignsSymbolInSetter(IPropertySymbol property, ISymbol symbol, SemanticModel semanticModel, CancellationToken cancellationToken) { var setMethod = property?.SetMethod; if (setMethod == null || setMethod.DeclaringSyntaxReferences.Length == 0) { return(false); } if (TryGetSetter(property, cancellationToken, out var setter)) { if (AssignmentWalker.FirstForSymbol(symbol, setter, Search.Recursive, semanticModel, cancellationToken)) { return(true); } } return(false); }
/// <summary> /// Check if any path returns a created IDisposable /// </summary> internal static Result IsAssignedWithCreated(ExpressionSyntax disposable, SemanticModel semanticModel, CancellationToken cancellationToken, out ISymbol assignedSymbol) { if (!IsPotentiallyAssignableTo(disposable, semanticModel, cancellationToken)) { assignedSymbol = null; return(Result.No); } if (semanticModel.GetSymbolSafe(disposable, cancellationToken) is IPropertySymbol property && property.TryGetSetter(cancellationToken, out var setter)) { using (var pooledSet = PooledHashSet <ISymbol> .Borrow()) { using (var pooledAssigned = AssignmentWalker.Borrow(setter, Search.Recursive, semanticModel, cancellationToken)) { foreach (var assigned in pooledAssigned.Assignments) { var symbol = semanticModel.GetSymbolSafe(assigned.Left, cancellationToken); if (IsPotentiallyAssignableTo(assigned.Left, semanticModel, cancellationToken) && (symbol is IFieldSymbol || symbol is IPropertySymbol)) { pooledSet.Add(symbol).IgnoreReturnValue(); } } } assignedSymbol = null; var result = Result.No; foreach (var symbol in pooledSet) { switch (IsAssignedWithCreated(symbol, disposable, semanticModel, cancellationToken)) { case Result.Unknown: if (result == Result.No) { assignedSymbol = symbol; result = Result.Unknown; } break; case Result.Yes: assignedSymbol = symbol; return(Result.Yes); case Result.AssumeYes: assignedSymbol = symbol; result = Result.AssumeYes; break; case Result.No: case Result.AssumeNo: break; default: throw new ArgumentOutOfRangeException(); } } return(result); } } using (var assignedValues = AssignedValueWalker.Borrow(disposable, semanticModel, cancellationToken)) { assignedSymbol = assignedValues.CurrentSymbol; if (assignedValues.Count == 1 && disposable.Parent is AssignmentExpressionSyntax assignment && assignment.Parent is ParenthesizedExpressionSyntax parenthesizedExpression && parenthesizedExpression.Parent is BinaryExpressionSyntax binary && binary.IsKind(SyntaxKind.CoalesceExpression)) { return(Result.No); } using (var recursive = RecursiveValues.Create(assignedValues, semanticModel, cancellationToken)) { return(IsAnyCreation(recursive, semanticModel, cancellationToken)); } } }