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();
        }
 private void Build(ClassMemberSyntax member, ClassBinder containingScope)
 {
     member.Match()
         .With<FieldSyntax>(field =>
         {
             Build(field.Type.Type, containingScope);
             if(field.InitExpression != null)
                 Build(field.InitExpression, containingScope);
         })
         .With<ConstructorSyntax>(constructor =>
         {
             foreach(var parameter in constructor.Parameters)
                 Build(parameter.Type.Type, containingScope);
             Binder scope = new FunctionBinder(containingScope);
             binders.Add(constructor, scope);
             foreach(var statement in constructor.Body)
                 scope = Build(statement, scope);
         })
         .With<DestructorSyntax>(destructor =>
         {
             foreach(var parameter in destructor.Parameters)
                 if(parameter.Type != null)
                     Build(parameter.Type.Type, containingScope);
             Binder scope = new FunctionBinder(containingScope);
             binders.Add(destructor, scope);
             foreach(var statement in destructor.Body)
                 scope = Build(statement, scope);
         })
         .With<IndexerMethodSyntax>(indexer =>
         {
             foreach(var parameter in indexer.Parameters)
                 if(parameter.Type != null)
                     Build(parameter.Type.Type, containingScope);
             // TODO deal with return type
             Binder scope = new FunctionBinder(containingScope);
             binders.Add(indexer, scope);
             foreach(var statement in indexer.Body)
                 scope = Build(statement, scope);
         })
         .With<MethodSyntax>(method =>
         {
             foreach(var parameter in method.Parameters)
                 if(parameter.Type != null)
                     Build(parameter.Type.Type, containingScope);
             // TODO deal with return type
             Binder scope = new FunctionBinder(containingScope);
             binders.Add(method, scope);
             foreach(var statement in method.Body)
                 scope = Build(statement, scope);
         })
         .Exhaustive();
 }