public override void Visit(SyntaxNode node) { // FIXME How comes a node can be null here? if (node != null) { if (supportedKinds.Contains(node.CSharpKind())) { currentBasicBlock.Statements.Add(node); } else if (node.IsKind(SyntaxKind.IfStatement)) { IfStatementSyntax ifNode = (IfStatementSyntax)node; ControlFlowBasicBlock conditionBasicBlock = currentBasicBlock; ControlFlowBasicBlock ifTrueBasicBlock = new ControlFlowBasicBlock(); ControlFlowBasicBlock afterIfBasicBlock = new ControlFlowBasicBlock(); conditionBasicBlock.Terminator = ifNode; Visit(ifNode.Condition); ifTrueBasicBlock.Successors.Add(afterIfBasicBlock); SetCurrentBasicBlock(ifTrueBasicBlock); Visit(ifNode.Statement); SetCurrentBasicBlock(afterIfBasicBlock); conditionBasicBlock.Successors.Add(ifTrueBasicBlock); conditionBasicBlock.Successors.Add(afterIfBasicBlock); } else { base.Visit(node); } } }
private static void Check(ControlFlowBasicBlock basicBlock, HashSet <ISymbol> nulls, SemanticModel semanticModel, Action <Diagnostic> addDiagnostic) { foreach (SyntaxNode node in basicBlock.Statements) { if (node.IsKind(SyntaxKind.SimpleAssignmentExpression)) { BinaryExpressionSyntax statement = (BinaryExpressionSyntax)node; ISymbol target = semanticModel.GetSymbolInfo(statement.Left).Symbol; if (target != null) { if (IsNull(statement.Right, nulls, semanticModel)) { nulls.Add(target); } else { nulls.Remove(target); } } } else if (node.IsKind(SyntaxKind.ReturnStatement)) { ReturnStatementSyntax statement = (ReturnStatementSyntax)node; if (IsNull(statement.Expression, nulls, semanticModel)) { addDiagnostic(Diagnostic.Create(Rule, statement.GetLocation())); } // End of control flow return; } else if (node.IsKind(SyntaxKind.EqualsExpression) || node.IsKind(SyntaxKind.NotEqualsExpression)) { BinaryExpressionSyntax statement = (BinaryExpressionSyntax)node; ISymbol target = null; bool isLeftNull = IsNull(statement.Left, nulls, semanticModel); bool isRightNull = IsNull(statement.Right, nulls, semanticModel); if (!isLeftNull && isRightNull) { target = semanticModel.GetSymbolInfo(statement.Left).Symbol; } else if (isLeftNull && !isRightNull) { target = semanticModel.GetSymbolInfo(statement.Right).Symbol; } if (target == null) { // nothing new was learnt, check both successors using the same state Check(basicBlock.Successors[0], nulls, semanticModel, addDiagnostic); Check(basicBlock.Successors[1], nulls, semanticModel, addDiagnostic); } else { // we're able to learn something new HashSet <ISymbol> leftNulls = new HashSet <ISymbol>(nulls); if (statement.IsKind(SyntaxKind.EqualsExpression)) { leftNulls.Add(target); } else { leftNulls.Remove(target); } HashSet <ISymbol> rightNulls = new HashSet <ISymbol>(nulls); if (statement.IsKind(SyntaxKind.EqualsExpression)) { rightNulls.Remove(target); } else { rightNulls.Add(target); } Check(basicBlock.Successors[0], leftNulls, semanticModel, addDiagnostic); Check(basicBlock.Successors[1], rightNulls, semanticModel, addDiagnostic); } } } if (basicBlock.Successors.Count == 1) { Check(basicBlock.Successors[0], nulls, semanticModel, addDiagnostic); } }
private void SetCurrentBasicBlock(ControlFlowBasicBlock newCurrentBasicBlock) { basicBlocks.Add(currentBasicBlock); currentBasicBlock = newCurrentBasicBlock; }