private void AddToken(SyntaxToken token) { if (_lastAddedToken.HasValue) { _graph.AddEdge(_lastAddedToken.Value, SourceGraphEdge.NextToken, token); } _lastAddedToken = token; }
public override void VisitReturnStatement(ReturnStatementSyntax node) { Debug.Assert(_returningPoint.Count > 0); if (node.Expression != null) { _graph.AddEdge(node.Expression, SourceGraphEdge.ReturnsTo, _returningPoint.Peek()); } base.VisitReturnStatement(node); }
private void VisitVariable(SyntaxToken identifierToken) { var curGuardInformation = _blockGuardInformation; while (curGuardInformation != null) { foreach (var validatedGuard in curGuardInformation.ValidatedGuards) { _graph.AddEdge(identifierToken, SourceGraphEdge.GuardedBy, validatedGuard.guardNode); } foreach (var invalidatedGuard in curGuardInformation.InvalidatedGuards) { _graph.AddEdge(identifierToken, SourceGraphEdge.GuardedByNegation, invalidatedGuard.guardNode); } curGuardInformation = curGuardInformation.EnclosingBlockInformation; } }
public static void AddDataFlowEdges(SourceGraph sourceGraph, SyntaxNodeOrToken tokenOfInterest, ICollection <SyntaxNodeOrToken> forbiddenNodes = null, ICollection <Edge <SyntaxNodeOrToken, SourceGraphEdge> > addedEdges = null) { var semanticModel = sourceGraph.SemanticModel; //There's nothing before the declaration, so we don't need to bother: if (sourceGraph.VariableDeclarationNodes.Contains(tokenOfInterest)) { return; } //We only ever need to visit each node once, so collect visited nodes here: var visitedNodes = new HashSet <(SyntaxNodeOrToken, bool)>(); //Start from all predecessors of the token of interest: var toVisit = new Stack <(SyntaxNodeOrToken node, bool haveFoundUse)>(); foreach (var(_, label, target) in sourceGraph.GetOutEdges(tokenOfInterest)) { if (label != SourceGraphEdge.LastUsedVariable || (forbiddenNodes?.Contains(target) ?? false)) { continue; } if (visitedNodes.Add((target, false))) { toVisit.Push((target, false)); } } var nodeOfInterest = tokenOfInterest.IsToken ? tokenOfInterest.AsToken().Parent : tokenOfInterest.AsNode(); ISymbol symbolToLookFor = nodeOfInterest != null?semanticModel.GetSymbolInfo(nodeOfInterest).Symbol?.OriginalDefinition : null; string nodeLabelToLookFor = tokenOfInterest.ToString(); while (toVisit.Count > 0) { var(node, haveFoundUse) = toVisit.Pop(); var nodeSyntaxNode = node.IsToken ? node.AsToken().Parent : node.AsNode(); var nodeSymbol = nodeSyntaxNode != null?semanticModel.GetSymbolInfo(nodeSyntaxNode).Symbol?.OriginalDefinition : null; bool matches; if (symbolToLookFor == null || nodeSymbol == null) { // This may happen in cases where Roslyn doesn't have symbol info // or when one of the nodes is a dummy node (and thus doesn't belong to the SyntaxTree) matches = node.ToString().Equals(nodeLabelToLookFor); } else { matches = nodeSymbol.Equals(symbolToLookFor); } if (matches) { if (!haveFoundUse) { var lastUseEdge = new Edge <SyntaxNodeOrToken, SourceGraphEdge>(tokenOfInterest, SourceGraphEdge.LastUse, node); if (sourceGraph.AddEdge(lastUseEdge)) { addedEdges?.Add(lastUseEdge); } haveFoundUse = true; } if (sourceGraph.VariableWriteNodes.Contains(node)) { var lastWriteEdge = new Edge <SyntaxNodeOrToken, SourceGraphEdge>(tokenOfInterest, SourceGraphEdge.LastWrite, node); if (sourceGraph.AddEdge(lastWriteEdge)) { addedEdges?.Add(lastWriteEdge); } //We are done with this path -- we found a use and a write! continue; } //There's nothing before the declaration, so we don't need to bother to recurse further: if (sourceGraph.VariableDeclarationNodes.Contains(node)) { continue; } } foreach (var(_, label, target) in sourceGraph.GetOutEdges(node)) { if (label != SourceGraphEdge.LastUsedVariable || (forbiddenNodes?.Contains(target) ?? false)) { continue; } if (visitedNodes.Add((target, haveFoundUse))) { toVisit.Push((target, haveFoundUse)); } } } }