How to retrieve type of SyntaxNode.Ascendants() and SyntaxNode.Descendants()

Answered How to retrieve type of SyntaxNode.Ascendants() and SyntaxNode.Descendants()

  • Monday, October 24, 2011 9:03 AM
     
      Has Code

    I cannot correctly retrieve the type of variables that are assigned to the SyntaxNode.Descendandts() or SyntaxNode.Ascanedants() functions. Successfully retrieved the type of any other kind of variables so far.

     

    A simple example:

    using System;
    using System.Linq;
    using Roslyn.Compilers;
    using Roslyn.Compilers.CSharp;
    
    namespace SemanticTypeError {
        class Program {
            static void Main(string[] args) {
                var varAEqualsTo5 = "var a = 5;";
                var simpleProgram = @"
    using System;
    using Roslyn.Compilers;
    using Roslyn.Compilers.CSharp;
    
    namespace SimpleNamespace {
        class SimpleClass {
            static void Main(string[] args) {
                    var sTree = SyntaxTree.ParseCompilationUnit(" + "@\"" + varAEqualsTo5 + "\"" + @");
                    var a = 5;
                    var b = sTree.Root.ChildNodes();
                    var c = sTree.Root.DescendentNodes();
                    var d = sTree.Root.Ancestors();
            }
        }
    }";
    
                var sTree = SyntaxTree.ParseCompilationUnit(simpleProgram);
                var compilation = Compilation.Create("test").AddSyntaxTrees(sTree).AddReferences(
                    new AssemblyFileReference(typeof(object).Assembly.Location),
                    new AssemblyFileReference(typeof(SyntaxTree).Assembly.Location),
                    new AssemblyFileReference(typeof(Roslyn.Compilers.Common.CommonSyntaxNode).Assembly.Location));
    
                Func<string, TypeSymbol> getTypeSymbol = name => compilation.GetSemanticModel(sTree).GetSemanticInfo(
                    sTree.Root.DescendentNodes().Where(node => node is VariableDeclarationSyntax).Cast<VariableDeclarationSyntax>().First(varDecl => varDecl.Variables.Any(var => var.Identifier.ValueText == name)).Type
                    ).Type;
    
                var typeA = getTypeSymbol("a");
                var typeB = getTypeSymbol("b");
                var typeC = getTypeSymbol("c");
                var typeD = getTypeSymbol("d");
            }
        }
    }

     

    After running this code, typeA and typeB are correctly assigned, but typeC and typeD have their TypeKind property set to TypeKind.Error. Their ErrorInfo says: "error CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code".

    I tried adding reference to every single DLL the Roslyn CTP installed and it resulted in the same behaviour.

     

    Am I doing something wrong here, or is this a limitation of the current CTP?

    • Edited by Whaeth Monday, October 24, 2011 9:16 AM
    •  

All Replies

  • Monday, October 24, 2011 11:00 AM
     
     Answered
    If you look at the methods, the difference between ChildNodes() and and DescendantNodes() is that DescendantNodes() has optional parameters. And optional parameters are among the as of yet unimplemented features of Roslyn.
    • Marked As Answer by Whaeth Monday, October 24, 2011 2:00 PM
    •  
  • Monday, October 24, 2011 1:51 PM
    Owner
     
     Answered Has Code

    svick is correct. If you pass default values to DescendentNodes() and Ancestors(), it should work fine:

    using System;
    using System.Linq;
    using Roslyn.Compilers;
    using Roslyn.Compilers.CSharp;
    
    namespace SemanticTypeError
    {
        class Program
        {
            static void Main(string[] args)
            {
                var varAEqualsTo5 = "var a = 5;";
                var simpleProgram = @"
    using System;
    using Roslyn.Compilers;
    using Roslyn.Compilers.CSharp;
    
    namespace SimpleNamespace {
        class SimpleClass {
            static void Main(string[] args) {
                    var sTree = SyntaxTree.ParseCompilationUnit(" + "@\"" + varAEqualsTo5 + "\"" + @");
                    var a = 5;
                    var b = sTree.Root.ChildNodes();
                    var c = sTree.Root.DescendentNodes(null, false);
                    var d = sTree.Root.Ancestors(true);
            }
        }
    }";
    
                var sTree = SyntaxTree.ParseCompilationUnit(simpleProgram);
                var compilation = Compilation.Create("test").AddSyntaxTrees(sTree).AddReferences(
                    new AssemblyFileReference(typeof(object).Assembly.Location),
                    new AssemblyFileReference(typeof(SyntaxTree).Assembly.Location),
                    new AssemblyFileReference(typeof(Roslyn.Compilers.Common.CommonSyntaxNode).Assembly.Location));
    
                Func<string, TypeSymbol> getTypeSymbol = name => compilation.GetSemanticModel(sTree).GetSemanticInfo(
                    sTree.Root.DescendentNodes()
                              .OfType<VariableDeclarationSyntax>()
                              .First(varDecl => varDecl.Variables.Any(var => var.Identifier.ValueText == name)).Type).Type;
    
                var typeA = getTypeSymbol("a");
                var typeB = getTypeSymbol("b");
                var typeC = getTypeSymbol("c");
                var typeD = getTypeSymbol("d");
            }
        }
    }
    


    Dustin Campbell | Senior Program Manager | Roslyn Visual Basic and C# Language Services
    • Marked As Answer by Whaeth Monday, October 24, 2011 2:00 PM
    •  
  • Monday, October 24, 2011 2:00 PM
     
     
    Hah! Thank you both.