private async Task<MethodDeclarationSyntax> GetMethodDeclaration(
            SyntaxNode node,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var invocationExpression = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.InvocationExpression));
            var methodSymbol = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken).Symbol as IMethodSymbol;
            if (methodSymbol == null)
            {
                return null;
            }

            var methodReference = methodSymbol.DeclaringSyntaxReferences.FirstOrDefault();
            if (methodReference == null)
            {
                return null;
            }

            var methodDeclaration = (await methodReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false)) as MethodDeclarationSyntax;
            if (methodDeclaration == null)
            {
                return null;
            }

            if (!methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)))
            {
                return null;
            }

            return methodDeclaration;
        }
        private IEnumerable<SyntaxNode> EnumerateNonRootChildren(SyntaxNode node)
        {
            foreach (var child in node.ChildNodes())
            {
                if (LambdaUtilities.IsLambdaBodyStatementOrExpression(child))
                {
                    continue;
                }

                if (HasLabel(child))
                {
                    yield return child;
                }
                else
                {
                    foreach (var descendant in child.DescendantNodes(DescendIntoChildren))
                    {
                        if (HasLabel(descendant))
                        {
                            yield return descendant;
                        }
                    }
                }
            }
        }
示例#3
0
 public override void DefaultVisit(SyntaxNode node)
 {
     foreach (var child in node.ChildNodes())
     {
         Visit(child);
     }
 }
示例#4
0
 public override void DefaultVisit(SyntaxNode node)
 {
     foreach (var child in node.ChildNodes())
     {
         child.Accept(this);
     }
 }
        public override Token Get(SyntaxNode node)
        {
            var valueText = node
                .DescendantNodes()
                .OfType<IdentifierNameSyntax>()
                .Last()
                .Identifier.ValueText;

            if (valueText == null)
            {
                throw new NotImplementedException();
            }

            var args = node.ChildNodes().OfType<ArgumentListSyntax>().First()
                .ChildNodes().OfType<ArgumentSyntax>().ToArray();

            var whenClause = args[0].ChildNodes().First();

            var block = args[1]
                .ChildNodes().OfType<ParenthesizedLambdaExpressionSyntax>().First()
                .ChildNodes().OfType<BlockSyntax>().First();

            var details = new WhenClosureDetails(whenClause, block);

            return new Token("WhenClosure", details);
        }
 private void Visit(SyntaxNode node, int spaces)
 {
     Console.WriteLine(new string(' ', spaces) + textVisitor.Visit(node));
     foreach (var child in node.ChildNodes())
     {
         Visit(child, spaces + 2);
     }
 }
        public override Token Get(SyntaxNode node)
        {
            var argument = node
                .ChildNodes().OfType<ArgumentListSyntax>().First()
                .ChildNodes().OfType<ArgumentSyntax>().First();

            var tokenDetails = GetDetails(argument);

            return new Token(Identifier(node).ToLower(), tokenDetails);
        }
示例#8
0
 public override void Visit(SyntaxNode node)
 {
     int padding = node.Ancestors().Count();
     //To identify leaf nodes vs nodes with children
     string prepend = node.ChildNodes().Any() ? "[-]"
     : "[.]";
     //Get the type of the node
     string line = new String(' ', padding) + prepend
     + " " + node.GetType().ToString();
     //Write the line
     System.Console.WriteLine(line);
     base.Visit(node);
 }
        protected override SyntaxNode GetTargetNode(SyntaxNode node)
        {
            if (node.IsKind(SyntaxKind.MemberBindingExpression))
            {
                var nameNode = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.IdentifierName));
                if (nameNode != null)
                {
                    return nameNode;
                }
            }

            return base.GetTargetNode(node);
        }
示例#10
0
        private SyntaxNode AddModifiers(SyntaxNode node, SyntaxToken syntaxToken)
        {
            // Get the first child node.
            SyntaxNode firstNode = node.ChildNodes().FirstOrDefault();

            if (firstNode != null)
            {
                // The leading trivia will be the method comments, if any.
                SyntaxTriviaList leadingTrivia = firstNode.GetLeadingTrivia();

                // Replace it with one without leading trivia.
                node = node.ReplaceNodes(
                    new[] { firstNode },
                    (a, b) => firstNode.WithLeadingTrivia());

                // Add the leading trivia to the new modifier.
                syntaxToken = syntaxToken.WithLeadingTrivia(leadingTrivia);
            }

            return node.AddModifiers(syntaxToken);
        }
示例#11
0
 protected void VisitChildren(SyntaxNode node) => VisitChildren(node.ChildNodes());
示例#12
0
 private IEnumerable <INamedTypeSymbol> GetNamespaceChildNodes <T>() where T : SyntaxNode
 {
     return(root.ChildNodes().OfType <NamespaceDeclarationSyntax>()
            .SelectMany(n => n.ChildNodes().OfType <T>())
            .Select(c => semanticModel.GetDeclaredSymbol(c) as INamedTypeSymbol));
 }
        /// <summary>
        /// Statement are all segment separate by semi-colon.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="state"></param>
        private VariableState VisitNode(SyntaxNode node, ExecutionState state)
        {
            //Logger.Log(node.GetType().ToString());

            switch (node)
            {
            case LocalDeclarationStatementSyntax localDeclaration:
                return(VisitLocalDeclaration(localDeclaration, state));

            case VariableDeclaratorSyntax variableDeclaration:
                return(VisitVariableDeclaration(variableDeclaration, state));

            case AssignmentStatementSyntax assignment:
                return(VisitAssignmentStatement(assignment, state));

            case ExpressionStatementSyntax expressionStatement:
                return(VisitExpressionStatement(expressionStatement, state));

            case ExpressionSyntax expression:
                return(VisitExpression(expression, state));

            case MethodBlockSyntax methodBlock:
                return(VisitMethodDeclaration(methodBlock, methodBlock.SubOrFunctionStatement.ParameterList, state));

            case ConstructorBlockSyntax constructorBlockSyntax:
                return(VisitMethodDeclaration(constructorBlockSyntax, constructorBlockSyntax.SubNewStatement.ParameterList, state));

            case PropertyBlockSyntax propertyBlockSyntax:
            {
                foreach (var accessor in propertyBlockSyntax.Accessors)
                {
                    VisitBlock(accessor, state);
                }

                return(new VariableState(node, VariableTaint.Unknown));
            }

            case ReturnStatementSyntax returnStatementSyntax:
                if (returnStatementSyntax.Expression == null)
                {
                    return(new VariableState(node, VariableTaint.Unknown));
                }

                return(VisitExpression(returnStatementSyntax.Expression, state));

            case ForEachStatementSyntax forEachSyntax:
                return(VisitForEach(forEachSyntax, state));
            }

            foreach (var n in node.ChildNodes())
            {
                VisitNode(n, state);
            }

            var isBlockStatement = node is IfStatementSyntax ||
                                   node is ForStatementSyntax;

            if (!isBlockStatement)
            {
                Logger.Log("Unsupported statement " + node.GetType() + " (" + node + ")");
            }

            return(new VariableState(node, VariableTaint.Unknown));
        }
示例#14
0
        public void Execute(GeneratorExecutionContext context)
        {
            if (context.SyntaxReceiver is not RecordSyntaxReceiver receiver)
            {
                throw new Exception();
            }

            foreach (var recordDeclaration in receiver.RecordDeclarations)
            {
                context.CancellationToken.ThrowIfCancellationRequested();

                if (recordDeclaration.ParameterList is null)
                {
                    continue;
                }

                var semanticModel = context.Compilation.GetSemanticModel(recordDeclaration.SyntaxTree);
                var currLocation = recordDeclaration.GetLocation();
                var currDeclaredSymbol = semanticModel.GetDeclaredSymbol(recordDeclaration);
                var canProcess = true;
                foreach (var location in currDeclaredSymbol!.Locations)
                {
                    if (currLocation.SourceSpan.Contains(location.SourceSpan) || location.SourceSpan.Contains(currLocation.SourceSpan))
                    {
                        continue;
                    }

                    var otherRecordDeclaration = location.SourceTree?.GetRoot()
                        .DescendantNodesAndSelf()
                        .OfType<RecordDeclarationSyntax>()
                        .Where(syntax =>
                            SymbolEqualityComparer.Default.Equals(
                                context.Compilation.GetSemanticModel(syntax.SyntaxTree).GetDeclaredSymbol(syntax),
                                currDeclaredSymbol))
                        .ToArray() ?? Enumerable.Empty<RecordDeclarationSyntax>();
                    if (otherRecordDeclaration.Any(syntax => syntax.HasDefaultCtor()))
                    {
                        canProcess = false;
                        break;
                    }
                }

                if (!canProcess)
                {
                    continue;
                }

                var recordName = recordDeclaration.Identifier.ToString();
                SyntaxNode root = recordDeclaration;
                List<UsingDirectiveSyntax> usings = new();
                List<string> wrappers = new();
                while (root.Parent != null)
                {
                    root = root.Parent;
                    if (root is TypeDeclarationSyntax tds)
                    {
                        if (!tds.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
                        {
                            throw new Exception("TADA"); // TODO
                        }
                        wrappers.Add($"{GetTypeDeclarationHeader(tds)}{Environment.NewLine}{{");
                    }

                    if (root is NamespaceDeclarationSyntax namespaceDeclaration)
                    {
                        var @namespace = namespaceDeclaration.Name.ToString();
                        wrappers.Add($"namespace {@namespace}{Environment.NewLine}{{");
                    }

                    usings.AddRange(root.ChildNodes().OfType<UsingDirectiveSyntax>());
                }

                wrappers.Reverse();

                // process parameters
                List<string> @params = new();
                var syntaxNodes = recordDeclaration.ParameterList.ChildNodes().ToList();

                foreach (var parameter in syntaxNodes.OfType<ParameterSyntax>())
                {
                    switch (parameter.Default?.Value)
                    {
                        case null:
                        case DefaultExpressionSyntax: // check if type actually matches
                        case LiteralExpressionSyntax lexs when lexs.IsKind(SyntaxKind.DefaultLiteralExpression):
                            var typeSymbol = ModelExtensions.GetTypeInfo(semanticModel, parameter.Type!).Type;
                            @params.Add($"default({typeSymbol})");
                            break;
                        default:  @params.Add(parameter.Default.Value.ToString());
                           break;
                    }
                }

                var code =
// @formatter:off
@$"
#pragma warning disable CS8019
    {string.Join(Environment.NewLine + "\t", usings)}
#pragma warning restore CS8019

    {string.Join(Environment.NewLine + "\t", wrappers)}
    {GetTypeDeclarationHeader(recordDeclaration)}
    {{
 private bool HasBlockChild(SyntaxNode node)
 {
     return node.ChildNodes().Any(n => n.Kind == SyntaxKind.Block);
 }
 private SyntaxNode GetFirstBlockChild(SyntaxNode node)
 {
     return node.ChildNodes().First(n => n.Kind == SyntaxKind.Block);
 }
示例#17
0
 private static bool HasBody(SyntaxNode node) => node.ChildNodes().AnyOfKind(SyntaxKind.Block);
示例#18
0
        /// <summary>
        ///algorithm copied from 
        /// http://stackoverflow.com/questions/1649027/how-do-i-print-out-a-tree-structure.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="indent"></param>
        /// <param name="last"></param>
        /// <returns></returns>
        private string PrintPretty(SyntaxNode node,string indent, bool last)
        {
            var sb = new StringBuilder();
            sb.Append(indent);
            if (last)
            {
                sb.Append("\\-");
                indent += "\t";
            }
            else
            {
                sb.Append("|-");
                indent += "|\t";
            }
            sb.AppendLine(node.Kind.ToString() + ":" + StringUtil.ReplaceNewLine(node.GetText(), ""));

            for (int i = 0; i < node.ChildNodes().Count() ; i++)
            {
                var child = node.ChildNodes().ElementAt(i);
                sb.Append(PrintPretty(child, indent, i == node.ChildNodes().Count() - 1));
            }

            return sb.ToString();
        }
        /// <summary>
        /// Adds a new internal class with the given name equivalent to the passed type to the given syntax tree.
        /// 
        /// Sets `created` to a reference to the newly created type.
        /// </summary>
        private static SyntaxNode AddType(NamedTypeSymbol equivTo, string withName, SyntaxNode tree, out TypeSyntax created)
        {
            created = Syntax.ParseTypeName(withName);

            var members =
                equivTo.GetMembers()
                .OfType<PropertySymbol>()
                .Select(
                    s =>
                    {
                        var prop =
                            Syntax.PropertyDeclaration(
                                null,
                                Syntax.TokenList(Syntax.ParseToken("public")),
                                Syntax.ParseTypeName(s.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                                null,
                                Syntax.Identifier(s.Name),
                                Syntax.AccessorList(
                                    Syntax.List(
                                        Syntax.AccessorDeclaration(
                                            SyntaxKind.GetAccessorDeclaration,
                                            null,
                                            Syntax.TokenList(),
                                            Syntax.ParseToken("get"),
                                            null,
                                            Syntax.ParseToken(";")
                                        ),
                                        Syntax.AccessorDeclaration(
                                            SyntaxKind.SetAccessorDeclaration,
                                            null,
                                            Syntax.TokenList(),
                                            Syntax.ParseToken("set"),
                                            null,
                                            Syntax.ParseToken(";")
                                        )
                                    )
                                )
                            );

                        return prop;
                    }
                )
                .Cast<MemberDeclarationSyntax>().ToList();

            var separators = new List<SyntaxToken>();
            for(var i = 0; i < members.Count - 1; i++) separators.Add(Syntax.ParseToken(","));

            var obj =
                Syntax.AnonymousObjectCreationExpression(
                    Syntax.SeparatedList(
                        equivTo.GetMembers()
                        .OfType<PropertySymbol>()
                        .Select(
                            p =>
                            {
                                var exp = Syntax.IdentifierName(p.Name);
                                return Syntax.AnonymousObjectMemberDeclarator(exp);
                            }
                        ),
                        separators
                    )
                ).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" "));

            // Build the ToString() method that anonymous types have to have
            var toStringRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("ToString"));
            var toStringAccess = Syntax.InvocationExpression(toStringRef);
            var toStringRet = Syntax.ReturnStatement(toStringAccess);
            var toStringStatements = Syntax.List<StatementSyntax>(toStringRet);
            var toStringBody =
                Syntax.Block(
                    Syntax.ParseToken("{"),
                    toStringStatements,
                    Syntax.ParseToken("}")
                );
            var toString =
                Syntax.MethodDeclaration(
                    null,
                    Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))),
                    Syntax.ParseTypeName("string").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    null,
                    Syntax.Identifier("ToString"),
                    null,
                    Syntax.ParameterList(),
                    null,
                    toStringBody
                );
            members.Add(toString);

            // Adding GetHashCode override anonymous types must have
            var hashCodeRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("GetHashCode"));
            var hashCodeAccess = Syntax.InvocationExpression(hashCodeRef);
            var hashCodeRet = Syntax.ReturnStatement(hashCodeAccess);
            var hashCodeStatements = Syntax.List<StatementSyntax>(hashCodeRet);
            var hashCodeBody =
                Syntax.Block(
                    Syntax.ParseToken("{"),
                    hashCodeStatements,
                    Syntax.ParseToken("}")
                );
            var hashCode =
                Syntax.MethodDeclaration(
                    null,
                    Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))),
                    Syntax.ParseTypeName("int").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    null,
                    Syntax.Identifier("GetHashCode"),
                    null,
                    Syntax.ParameterList(),
                    null,
                    hashCodeBody
                );
            members.Add(hashCode);

            // Adding Equals method anonymous types must have
            var equalsAs = Syntax.ParseExpression("o as " + withName);
            var equalsAssign =
                Syntax.VariableDeclaration(
                    created.WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    Syntax.SeparatedList(
                        Syntax.VariableDeclarator(
                            Syntax.Identifier("other"),
                            null,
                            Syntax.EqualsValueClause(equalsAs)
                        )
                    )
                );
            var equalsEqualsRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("Equals"));
            var equalsAccess = Syntax.InvocationExpression(equalsEqualsRef, Syntax.ArgumentList(Syntax.SeparatedList(Syntax.Argument(Syntax.ParseExpression("o")))));
            var equalsIf =
                Syntax.IfStatement(
                    Syntax.ParseExpression("other == null"),
                    Syntax.ReturnStatement(equalsAccess)
                );
            var equalsEqualsExps =
                equivTo.GetMembers()
                .OfType<PropertySymbol>()
                .Select(
                    p =>
                    {
                        var n = p.Name;
                        ExpressionSyntax ret;

                        if (p.Type.IsReferenceType)
                        {
                            var strExp = "(" + n + " != null ? " + n + ".Equals(other." + n + ") : (other." + n + " != null ? other." + n + ".Equals(" + n + ") : true ))";

                            ret = Syntax.ParseExpression(strExp);
                        }
                        else
                        {
                            ret = Syntax.ParseExpression(n + " == other." + n);
                        }

                        return ret.WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "));
                    }
                ).ToList();
            ExpressionSyntax equalsBinary = equalsEqualsExps.First();
            for (var i = 1; i < equalsEqualsExps.Count; i++) equalsBinary = Syntax.BinaryExpression(SyntaxKind.LogicalAndExpression, equalsBinary, equalsEqualsExps[i]);
            var equalsBinaryRet = Syntax.ReturnStatement(equalsBinary.WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")));
            var equalsStatements =
                Syntax.List(
                    (StatementSyntax)Syntax.LocalDeclarationStatement(equalsAssign),
                    (StatementSyntax)equalsIf,
                    (StatementSyntax)equalsBinaryRet
                );
            var equalsBody =
                Syntax.Block(
                    Syntax.ParseToken("{"),
                    equalsStatements,
                    Syntax.ParseToken("}")
                );
            var equals =
                Syntax.MethodDeclaration(
                    null,
                    Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))),
                    Syntax.ParseTypeName("bool").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    null,
                    Syntax.Identifier("Equals"),
                    null,
                    Syntax.ParameterList(
                        Syntax.SeparatedList(
                            Syntax.Parameter(
                                null,
                                Syntax.TokenList(),
                                Syntax.ParseTypeName("object").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                                Syntax.Identifier("o"),
                                null
                            )
                        )
                    ),
                    null,
                    equalsBody
                );
            members.Add(equals);

            var equiv =
                Syntax.ClassDeclaration(
                    null,
                    Syntax.ParseToken("internal").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    Syntax.Identifier(withName).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")),
                    null,
                    null,
                    null,
                    Syntax.List<MemberDeclarationSyntax>(members)
                );

            var namespaces = tree.ChildNodes().OfType<NamespaceDeclarationSyntax>();

            if (namespaces.Count() == 0 || namespaces.Count() > 1)
            {
                // HACK, better way to insert classes should be considered
                throw new Exception("Making some assumptions about namespaces, you can only have 1");
            }

            var @namespace = namespaces.Single();

            var updated =
                @namespace.WithMembers(
                    @namespace.Members.Add(equiv)
                );

            return tree.ReplaceNode(@namespace, updated);
        }
 private static bool TryGetChildTypeNode(SyntaxNode node, out SyntaxNode childTypeNode)
 {
     childTypeNode = node.ChildNodes().Where(x => x.IsKind(SyntaxKind.IdentifierName) || x.IsKind(SyntaxKind.PredefinedType) || x.IsKind(SyntaxKind.GenericName) || x.IsKind(SyntaxKind.ArrayType) || x.IsKind(SyntaxKind.TupleType)).FirstOrDefault();
     return(childTypeNode != null);
 }
示例#21
0
        private void LogSyntaxTree(SyntaxNode node, StringBuilder builder, int ident = 0, bool skipSelf = false)
        {
            string sident = String.Empty;
            for (int i = 0; i < ident; ++i)
                sident += "\t";

            if (!skipSelf)
            {
                builder.AppendLine (sident + node.GetType() + ": " + node);
                ident++;
            }

            foreach (SyntaxNode childNode in node.ChildNodes())
                LogSyntaxTree (childNode, builder, ident);
        }
        /// <summary>
        /// Statement are all segment separate by semi-colon.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="state"></param>
        private VariableState VisitNode(SyntaxNode node, ExecutionState state)
        {
            //Logger.Log(node.GetType().ToString());

            switch (node)
            {
            case LocalDeclarationStatementSyntax declarationStatementSyntax:
                return(VisitLocalDeclaration(declarationStatementSyntax, state));

            case VariableDeclarationSyntax variableDeclarationSyntax:
                return(VisitVariableDeclaration(variableDeclarationSyntax, state));

            case ExpressionStatementSyntax expressionStatementSyntax:
                return(VisitExpressionStatement(expressionStatementSyntax, state));

            case ExpressionSyntax expressionSyntax:
                return(VisitExpression(expressionSyntax, state));

            case MethodDeclarationSyntax methodDeclarationSyntax:
                return(VisitMethodDeclaration(methodDeclarationSyntax, state));

            case ConstructorDeclarationSyntax constructorDeclarationSyntax:
                return(VisitMethodDeclaration(constructorDeclarationSyntax, state));

            case DestructorDeclarationSyntax destructorDeclarationSyntax:
                return(VisitMethodDeclaration(destructorDeclarationSyntax, state));

            case PropertyDeclarationSyntax propertyDeclarationSyntax:
            {
                if (propertyDeclarationSyntax.ExpressionBody != null)
                {
                    return(VisitNode(propertyDeclarationSyntax.ExpressionBody, state));
                }

                foreach (var accessor in propertyDeclarationSyntax.AccessorList.Accessors)
                {
                    if (accessor.Body != null)
                    {
                        VisitBlock(accessor.Body, state);
                    }
                }

                return(new VariableState(node, VariableTaint.Unknown));
            }

            case ReturnStatementSyntax returnStatementSyntax:
                if (returnStatementSyntax.Expression == null)
                {
                    return(new VariableState(node, VariableTaint.Unknown));
                }

                return(VisitExpression(returnStatementSyntax.Expression, state));

            case ForEachStatementSyntax forEachSyntax:
                return(VisitForEach(forEachSyntax, state));

            case BlockSyntax blockSyntax:
                return(VisitBlock(blockSyntax, state));
            }

            foreach (var n in node.ChildNodes())
            {
                VisitNode(n, state);
            }

            var isBlockStatement = node is IfStatementSyntax ||
                                   node is ForStatementSyntax;

            if (!isBlockStatement)
            {
                Logger.Log("Unsupported statement " + node.GetType() + " (" + node + ")");
            }

            return(new VariableState(node, VariableTaint.Unknown));
        }