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();
 }