private static string NameInScope(int depth, DeclarationSyntax syntax)
 {
     return(syntax.Match().Returning <SyntaxToken>()
            .With <NamespaceSyntax>(ns => ns.Names[depth])
            .With <EntitySyntax>(e => e.Name)
            .Exhaustive()
            .ValueText);
 }
        public void Build(DeclarationSyntax declaration, ContainerBinder containingScope)
        {
            declaration.Match()
            .With <NamespaceSyntax>(@namespace =>
            {
                var imports    = @namespace.UsingDirectives.SelectMany(u => GatherImportedSymbols(u, containingScope));
                var namesCount = @namespace.Names.Count;
                for (var i = 0; i < namesCount; i++)
                {
                    var name        = @namespace.Names[i];
                    var last        = i == namesCount - 1;
                    var reference   = containingScope.GetMembers(name.ValueText).OfType <NamespaceReference>().Single();
                    containingScope = new NamespaceBinder(containingScope, reference, last ? imports : Enumerable.Empty <ImportedSymbol>());
                    // The innermost binder is the one that has the imports and should be associated with the syntax node
                    if (last)
                    {
                        binders.Add(@namespace, containingScope);
                    }
                }

                foreach (var member in @namespace.Members)
                {
                    Build(member, containingScope);
                }
            })
            .With <ClassSyntax>(@class =>
            {
                var scope = new ClassBinder(containingScope, @class);
                binders.Add(@class, scope);
                foreach (var member in @class.Members)
                {
                    Build(member, scope);
                }
            })
            .With <FunctionSyntax>(function =>
            {
                foreach (var parameter in function.Parameters)
                {
                    Build(parameter.Type.Type, containingScope);
                }
                // TODO deal with return type
                Binder scope = new FunctionBinder(containingScope);
                binders.Add(function, scope);
                foreach (var statement in function.Body)
                {
                    scope = Build(statement, scope);
                }
            })
            //		.With<VariableDeclaration>(global =>
            //		{
            //			global.Type.BindNames(scope);
            //			global.InitExpression?.BindNames(scope);
            //		})
            .Exhaustive();
        }
        public void Build(DeclarationSyntax declaration, ContainerBinder containingScope)
        {
            declaration.Match()
                .With<NamespaceSyntax>(@namespace =>
                {
                    var imports = @namespace.UsingDirectives.SelectMany(u => GatherImportedSymbols(u, containingScope));
                    var namesCount = @namespace.Names.Count;
                    for(var i = 0; i < namesCount; i++)
                    {
                        var name = @namespace.Names[i];
                        var last = i == namesCount - 1;
                        var reference = containingScope.GetMembers(name.ValueText).OfType<NamespaceReference>().Single();
                        containingScope = new NamespaceBinder(containingScope, reference, last ? imports : Enumerable.Empty<ImportedSymbol>());
                        // The innermost binder is the one that has the imports and should be associated with the syntax node
                        if(last)
                            binders.Add(@namespace, containingScope);
                    }

                    foreach(var member in @namespace.Members)
                        Build(member, containingScope);
                })
                .With<ClassSyntax>(@class =>
                {
                    var scope = new ClassBinder(containingScope, @class);
                    binders.Add(@class, scope);
                    foreach(var member in @class.Members)
                        Build(member, scope);
                })
                .With<FunctionSyntax>(function =>
                {
                    foreach(var parameter in function.Parameters)
                        Build(parameter.Type.Type, containingScope);
                    // TODO deal with return type
                    Binder scope = new FunctionBinder(containingScope);
                    binders.Add(function, scope);
                    foreach(var statement in function.Body)
                        scope = Build(statement, scope);
                })
                //		.With<VariableDeclaration>(global =>
                //		{
                //			global.Type.BindNames(scope);
                //			global.InitExpression?.BindNames(scope);
                //		})
                .Exhaustive();
        }