private object FindAssignedConstant(SyntaxNode node, SemanticModel nodeSemanticModel, HashSet <SyntaxNode> visitedVariables) { return(node is TIdentifierNameSyntax identifier ? FindConstant(assignmentFinder.FindLinearPrecedingAssignmentExpression(IdentifierName(identifier), node, FindFieldInitializer), visitedVariables) : null); SyntaxNode FindFieldInitializer() { if (nodeSemanticModel.GetSymbolInfo(identifier).Symbol is IFieldSymbol fieldSymbol && VariableDeclarator(fieldSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax()) is { } variable && (visitedVariables == null || !visitedVariables.Contains(variable))) { visitedVariables ??= new HashSet <SyntaxNode>(); visitedVariables.Add(variable); return(InitializerValue(variable)); }
public bool IsInvalidBuilderInitialization(InvocationContext context) { var current = context.Node; while (current != null) { current = RemoveParentheses(current); if (current is TInvocationSyntax invocation) { var invocationContext = new InvocationContext(invocation, GetIdentifierName(invocation), context.SemanticModel); if (descriptors.FirstOrDefault(x => x.IsMatch(invocationContext)) is { } desc) { return(!desc.IsValid(invocation)); } current = GetExpression(invocation); } else if (IsMemberAccess(current, out var memberAccessExpression)) { current = memberAccessExpression; } else if (IsObjectCreation(current)) { // We're sure that full invocation chain started here => we've seen all configuration invocations. return(!constructorIsSafe); } else if (IsIdentifier(current, out var identifierName)) { if (!(context.SemanticModel.GetSymbolInfo(current).Symbol is ILocalSymbol)) { return(false); } // When tracking reaches the local variable in invocation chain 'variable.MethodA().MethodB()' // we'll try to find preceding assignment to that variable to continue inspection of initialization chain. current = assignmentFinder.FindLinearPrecedingAssignmentExpression(identifierName, current); } else { return(false); } } return(false); }