private static Result IsCreationCore(RecursiveValues values, SemanticModel semanticModel, CancellationToken cancellationToken) { values.Reset(); var result = Result.No; while (values.MoveNext()) { switch (IsCreationCore(values.Current, semanticModel, cancellationToken)) { case Result.Unknown: if (result == Result.No) { result = Result.Unknown; } break; case Result.Yes: return(Result.Yes); case Result.No: break; case Result.Maybe: result = Result.Maybe; break; default: throw new ArgumentOutOfRangeException(); } } return(result); }
private static bool IsPotentiallyCachedOrInjectedCore(ExpressionSyntax value, SemanticModel semanticModel, CancellationToken cancellationToken) { var symbol = semanticModel.GetSymbolSafe(value, cancellationToken); if (IsInjectedCore(symbol) == Result.Yes) { return(true); } if (symbol is IPropertySymbol property && !property.IsAutoProperty(cancellationToken)) { using (var returnValues = ReturnValueWalker.Create(value, Search.TopLevel, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(returnValues.Item, semanticModel, cancellationToken)) { return(IsInjectedCore(recursive, semanticModel, cancellationToken) .IsEither(Result.Yes, Result.Maybe)); } } } using (var sources = AssignedValueWalker.Create(value, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(sources.Item, semanticModel, cancellationToken)) { return(IsInjectedCore(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe)); } } }
/// <summary> /// Check if any path returns a created IDisposable /// </summary> internal static Result IsCreation(ExpressionSyntax candidate, SemanticModel semanticModel, CancellationToken cancellationToken) { if (!IsPotentiallyAssignableTo(candidate, semanticModel, cancellationToken) || candidate is ThisExpressionSyntax || candidate is BaseExpressionSyntax) { return(Result.No); } using (var pooled = ReturnValueWalker.Create(candidate, Search.Recursive, semanticModel, cancellationToken)) { if (pooled.Item.Count == 0) { var symbol = semanticModel.GetSymbolSafe(candidate, cancellationToken); if (symbol != null && symbol.DeclaringSyntaxReferences.Length == 0) { return(IsCreationCore(candidate, semanticModel, cancellationToken)); } using (var recursive = RecursiveValues.Create(new[] { candidate }, semanticModel, cancellationToken)) { return(IsCreationCore(recursive, semanticModel, cancellationToken)); } } using (var recursive = RecursiveValues.Create(pooled.Item, semanticModel, cancellationToken)) { return(IsCreationCore(recursive, semanticModel, cancellationToken)); } } }
private static Result IsAssignedWithCreated(RecursiveValues walker, SemanticModel semanticModel, CancellationToken cancellationToken) { if (walker.Count == 0) { return(Result.No); } return(IsCreationCore(walker, semanticModel, cancellationToken)); }
internal static Result IsAssignedWithCreated(ISymbol symbol, SyntaxNode context, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooled = AssignedValueWalker.Create(symbol, context, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(pooled.Item, semanticModel, cancellationToken)) { return(IsAssignedWithCreated(recursive, semanticModel, cancellationToken)); } } }
internal static Result IsAssignedWithCreated(IFieldSymbol field, SemanticModel semanticModel, CancellationToken cancellationToken) { if (!IsPotentiallyAssignableTo(field?.Type)) { return(Result.No); } using (var pooled = AssignedValueWalker.Create(field, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(pooled.Item, semanticModel, cancellationToken)) { return(IsAssignedWithCreated(recursive, semanticModel, cancellationToken)); } } }
internal static bool IsAssignedWithCreatedAndNotCachedOrInjected(IFieldSymbol field, SemanticModel semanticModel, CancellationToken cancellationToken) { if (field == null || !IsPotentiallyAssignableTo(field.Type)) { return(false); } using (var sources = AssignedValueWalker.Create(field, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(sources.Item, semanticModel, cancellationToken)) { return(IsAssignedWithCreated(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe) && !IsInjectedCore(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe)); } } }
internal static bool IsAssignedWithCreatedAndInjected(IPropertySymbol property, SemanticModel semanticModel, CancellationToken cancellationToken) { if (property == null || !IsPotentiallyAssignableTo(property.Type)) { return(false); } using (var sources = AssignedValueWalker.Create(property, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(sources.Item, semanticModel, cancellationToken)) { return(IsAssignedWithCreated(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe) && IsInjectedCore(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe)); } } }
/// <summary> /// Check if any path returns a created IDisposable /// </summary> internal static bool IsPotentiallyCachedOrInjected(InvocationExpressionSyntax disposeCall, SemanticModel semanticModel, CancellationToken cancellationToken) { if (!TryGetDisposedRootMember(disposeCall, semanticModel, cancellationToken, out ExpressionSyntax member)) { return(false); } var symbol = semanticModel.GetSymbolSafe(member, cancellationToken); if (IsInjectedCore(symbol).IsEither(Result.Yes, Result.Maybe)) { return(true); } using (var sources = AssignedValueWalker.Create(symbol, disposeCall, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(sources.Item, semanticModel, cancellationToken)) { return(IsInjectedCore(recursive, semanticModel, cancellationToken).IsEither(Result.Yes, Result.Maybe)); } } }
private static Result IsInjectedCore(RecursiveValues values, SemanticModel semanticModel, CancellationToken cancellationToken) { if (values.Count == 0) { return(Result.No); } var result = Result.No; values.Reset(); while (values.MoveNext()) { if (values.Current is ElementAccessExpressionSyntax elementAccess) { var symbol = semanticModel.GetSymbolSafe(elementAccess.Expression, cancellationToken); var isInjected = IsInjectedCore(symbol); if (isInjected == Result.Yes) { return(Result.Yes); } if (isInjected == Result.Maybe) { result = Result.Maybe; } using (var sources = AssignedValueWalker.Create(values.Current, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(sources.Item, semanticModel, cancellationToken)) { isInjected = IsInjectedCore(recursive, semanticModel, cancellationToken); if (isInjected == Result.Yes) { return(Result.Yes); } if (isInjected == Result.Maybe) { result = Result.Maybe; } } } } else { var symbol = semanticModel.GetSymbolSafe(values.Current, cancellationToken); var isInjected = IsInjectedCore(symbol); if (isInjected == Result.Yes) { return(Result.Yes); } if (isInjected == Result.Maybe) { result = Result.Maybe; } } } return(result); }
/// <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 AccessorDeclarationSyntax setter)) { using (var pooledSet = SetPool <ISymbol> .Create()) { using (var pooledAssigned = Assignment.Create(setter, Search.Recursive, semanticModel, cancellationToken)) { foreach (var assigned in pooledAssigned.Item.Assignments) { var symbol = semanticModel.GetSymbolSafe(assigned.Left, cancellationToken); if (IsPotentiallyAssignableTo(assigned.Left, semanticModel, cancellationToken) && (symbol is IFieldSymbol || symbol is IPropertySymbol)) { pooledSet.Item.Add(symbol).IgnoreReturnValue(); } } } assignedSymbol = null; var result = Result.No; foreach (var symbol in pooledSet.Item) { 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.No: break; case Result.Maybe: assignedSymbol = symbol; result = Result.Maybe; break; default: throw new ArgumentOutOfRangeException(); } } return(result); } } using (var pooled = AssignedValueWalker.Create(disposable, semanticModel, cancellationToken)) { using (var recursive = RecursiveValues.Create(pooled.Item, semanticModel, cancellationToken)) { assignedSymbol = pooled.Item.CurrentSymbol; return(IsAssignedWithCreated(recursive, semanticModel, cancellationToken)); } } }