private void EmitMethod(DeclarationEmitContext dgc, string id, IEnumerable<ParameterSyntax> parameters, SyntaxNode body)
        {
            var ltype = dgc.LType;
            var qname = ltype.ID + "." + id;

            TraceEmit("  method '{0}' ...", id);

            var rtype = ltype.RType;
            var ps = TranslateMethodParameters(parameters);

            var jsw = new JScriptWriter();
            jsw.Write(GetPrototypeClause(ltype, id) + " = function(" + ps + ")");

            // method context
            var context = ModuleFactory.CreateMethodContext((IDeclarationContext)ltype);

            // CS to JS rewriter using the method context.
            var rewriter = CreateRewriter(dgc, context);

            // parameter variables 
            rewriter.AddMethodParameters(parameters);

            if (null == body)
            {
                Trace("WARNING: method " + id + " has no body.");
                return;
            }

            // convert the method body
            var node = rewriter.Visit(body);

            // prefix with the 'this' replacement
            node = AddLambdaThis(node);

            // and emit the JS method declaration
            jsw.WriteLine(node.ToString());
            dgc.Writer.Write(jsw);
        }
        /// <summary>
        /// Generates code for a given class type and associates it with the type item.
        /// </summary>
        /// <param name="ltype">The class type item to generate.</param>
        /// <remarks>
        /// <para>The DeclarationEmitContext will be set as the EmitContext.</para></remarks>
        private void EmitClass(ITypeItem ltype)
        {
            if (Log.ShowClassDependencies || Log.ShowCodeGeneration)
            {
                Log.Trace("generate class [{0}] ...", ltype.ID);
            }

            if(null != ltype.EmitContext)
            {
                throw new InvalidOperationException("item " + ltype + " already has an emit context.");
            }

            try
            {
                CurrentClass = ltype;

                var dsc = (DeclarationSourceContext)ltype.SourceNode;
                var cls = (ClassDeclarationSyntax)dsc.ClassDeclaration;

                // create emit context
                var dgc = new DeclarationEmitContext(ltype, dsc);
                ltype.SetEmitContext(dgc);
                dgc.OnItemReferenced = ItemReferenced;

                dgc.AddItemReferences();

                // look for automatic properties
                var autoprops = cls.Members
                    .OfType<PropertyDeclarationSyntax>()
                    .Where(IsAutomaticProperty)
                    .Select(ap => ap.Identifier.ToString());



                EmitConstructor(dgc, autoprops);

                var classmembers = ltype as IVariableContext;

                // add member methods and properties ...
                foreach (var member in cls.Members)
                {
                    if (member is MethodDeclarationSyntax)
                    {
                        var method = member as MethodDeclarationSyntax;
                        var name = method.Identifier.ToString();
                        var v = classmembers.GetVariable(name);
                        if (!v.DoNotGenerate)
                        {
                            EmitMethod(dgc, method);
                        }
                    }
                    else if (member is PropertyDeclarationSyntax)
                    {
                        var prop = (PropertyDeclarationSyntax)member;
                        var propname = prop.Identifier.ToString();

                        /*Trace("property {0}:", propname);
                        SyntaxTreeHelper.PrintTree(prop);*/

                        if (IsAutomaticProperty(prop))
                        {
                            // automatic property 
                            EmitAutomaticPropertyAccessors(dgc, prop);
                        }
                        else
                        {
                            // emit property accessors
                            foreach (var acc in member.DescendantNodes().OfType<AccessorDeclarationSyntax>())
                            {
                                if (acc.Keyword.ToString() == "get")
                                {
                                    EmitGetAccessor(dgc, "get_" + propname, acc.Body);
                                }
                                else
                                {
                                    EmitSetAccessor(dgc, "set_" + propname, acc.Body);
                                }
                            }
                        }
                    }
                    else if (member is EventFieldDeclarationSyntax)
                    {
                        // done LMGMELDMQ7
                    }
                    else if (member is FieldDeclarationSyntax)
                    {
                        // done LN4NL4H5PI
                    }
                    else if (member is ConstructorDeclarationSyntax)
                    {
                        // handled before
                    }
                    else if (member is EnumDeclarationSyntax)
                    {
                        // skip nested
                    }
                    else if (member is ClassDeclarationSyntax)
                    {
                        // skip nested
                    }
                    else
                    {
                        Log.Warning("skipped production [{0}] while generating class code.", member.GetType().Name);
                        SyntaxTreeHelper.PrintTree(member);
                    }
                }
            }
            finally
            {
                CurrentClass = null;
            }
        }
 private void EmitSetAccessor(DeclarationEmitContext dgc, string name, SyntaxNode body)
 {
     var z = SyntaxFactory.ParseParameterList("object value;");
     EmitMethod(dgc, name, z.DescendantNodes().OfType<ParameterSyntax>(), body);
 }
 private void EmitMethod(DeclarationEmitContext dgc, MethodDeclarationSyntax m)
 {
     var args = m.ParameterList.DescendantNodes().OfType<ParameterSyntax>();
     EmitMethod(dgc, m.Identifier.ToString(), args, m.Body);
 }
        private void EmitConstructor(DeclarationEmitContext dgc, IEnumerable<string> autoprops)
        {
            var ltype = dgc.LType;
            var rtype = ltype.RType;
            var typename = ltype.CodeName;

            var declctx = (IDeclarationContext)ltype;

            // method context for constructor
            var context = ModuleFactory.CreateMethodContext(declctx);

            // rewriter
            var rewriter = CreateRewriter(dgc, context);

            // writer receiving constructor and related code.
            JScriptWriter jsw = new JScriptWriter();

            // initialize the prototype
            string basename = null;
            if (null != ltype.BaseType)
            {
                if (null != ltype.BaseType.RType)
                {
                    basename = ltype.BaseType.CodeName;
                    jsw.WriteLine(typename + ".prototype = new " + basename + "();");
                    jsw.WriteLine(typename + ".prototype.constructor = " + typename + ";");
                }
            }

            // static
            EmitStaticInitializer(dgc, jsw);

            // analyze constructors ...
            var cls = dgc.Source.ClassDeclaration;
            var constructors = cls.Members.OfType<ConstructorDeclarationSyntax>();
            if (constructors.Count() > 1)
            {
                throw new Exception("multiple constructors are not supported [" + typename + "].");
            }

            var constructor = constructors.FirstOrDefault();
            var ps = string.Empty;
            if (null != constructor)
            {
                var parameters = constructor.ParameterList.ChildNodes().OfType<ParameterSyntax>();
                rewriter.AddMethodParameters(parameters);
                ps = TranslateMethodParameters(parameters);
            }


            // constructor method
            jsw.WriteLine("function " + typename + "(" + ps + ")");
            jsw.EnterBlock();

            // call base constructor
            if (null != basename)
            {
                jsw.WriteLine(basename + ".prototype.constructor.call(this);");
            }

            // type identifier
            jsw.WriteLine("this.$type = '" + typename + "';");

            // initialize our 'this' replacement.
            var cthis = CreateLambdaThis();
            jsw.Write(cthis.ToString());

            foreach (var ap in autoprops)
            {
                jsw.Write(Settings.OuterThis + "." + DeriveAutomaticName(ap) + " = null;");
            }

            foreach (var dp in dgc.DependencyPropertyInitializations)
            {
                // TODO: constant management required.
                //var dvalue = dp.DefaultMetadata.DefaultValue;
                object dvalue = null;
                if (null == dvalue)
                {
                    jsw.Write(Settings.OuterThis + ".InitValue(\"" + dp.Name + "\");");
                }
                else
                {
                    jsw.Write(Settings.OuterThis + ".InitValue(\"" + dp.Name + "\", " + dvalue + ");");
                }
            }

            // field initializers and constructor body ...
            EmitConstructorFields(dgc, rewriter, jsw);

            jsw.LeaveBlock();

            // commit to class output
            dgc.Writer.Write(jsw);
        }
 private void EmitGetAccessor(DeclarationEmitContext dgc, string name, SyntaxNode body)
 {
     EmitMethod(dgc, name, null, body);
 }
        private void EmitConstructorFields(DeclarationEmitContext dgc, CSharpToJScriptRewriter rewriter, JScriptWriter jsw)
        {
            var info = dgc.LType;
            var rtype = info.RType;

            var cls = dgc.Source.ClassDeclaration;

            // emit class member fields (LN4NL4H5PI)
            foreach (var fielddecl in cls.ChildNodes().OfType<FieldDeclarationSyntax>())
            {
                foreach (var declarator in fielddecl.DescendantNodes().OfType<VariableDeclaratorSyntax>())
                {
                    var id = declarator.Identifier.ToString();
                    if (null != rtype)
                    {
                        var field = rtype.GetField(id, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                        if (null != field && field.IsStatic)
                        {
                            continue;
                        }
                    }

                    // identifier, prepend 'this'.
                    //var idsyntax = SyntaxFactory.IdentifierName(declarator.Identifier);
                    var idsyntax = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxFactory.IdentifierName(Settings.OuterThis),
                        SyntaxFactory.IdentifierName(declarator.Identifier)
                        );
                    var idnode = rewriter.Visit(idsyntax);
                    jsw.Write(idnode.ToString());

                    var equals = declarator.ChildNodes().FirstOrDefault();
                    if (null != equals)
                    {
                        var node = rewriter.Visit(equals);
                        jsw.Write(node.ToString());
                    }
                    else
                    {
                        jsw.Write(" = null");
                    }

                    jsw.WriteLine(";");
                }
            }

            // event objects (LMGMELDMQ7)
            foreach (var ev in cls.Members.OfType<EventFieldDeclarationSyntax>())
            {
                foreach (var v in ev.Declaration.Variables)
                {
                    // initialize event object to null, as in C#
                    var id = Settings.OuterThis + "." + v.Identifier;
                    jsw.WriteLine(id + " = null;");

                    jsw.WriteLine("this.add_" + v.Identifier + " = function(h) {");
                    jsw.WriteLine(id + " = Delegate.Combine(" + id + ", h); };");
                    jsw.WriteLine("this.remove_" + v.Identifier + " = function(h) {");
                    jsw.WriteLine(id + " = Delegate.Remove(" + id + ", h); };");
                    jsw.WriteLine("this.fire_" + v.Identifier + " = function(sender, e) {");
                    jsw.WriteLine("Delegate.Fire(" + id + ", sender, e); };");
                }
            }

            // constructor
            var constructor = cls.Members.OfType<ConstructorDeclarationSyntax>().FirstOrDefault();
            if (null != constructor)
            {
                foreach (var stmt in constructor.Body.Statements)
                {
                    var ctor = rewriter.Visit(stmt);
                    // ctor = AddLambdaThis(ctor);
                    jsw.Write(ctor.ToString());
                }
            }
        }
 private void EmitAutomaticPropertyInitializer(DeclarationEmitContext dgc, string membername)
 {
     var prop = dgc.LType.GetMember(membername);
 }
        private void EmitAutomaticPropertyAccessors(DeclarationEmitContext dgc, PropertyDeclarationSyntax propsyntax)
        {
            var ltype = dgc.LType;
            var prop = ltype.GetMember(propsyntax.Identifier.ToString());
            var name = prop.CodeName;

            dgc.Writer.WriteLine(GetPrototypeClause(ltype, "get_" + name) + " = function() { return this." + DeriveAutomaticName(name) + "; }");
            dgc.Writer.WriteLine(GetPrototypeClause(ltype, "set_" + name) + " = function(value) { this." + DeriveAutomaticName(name) + " = value; }");
        }
        private void EmitStaticInitializer(DeclarationEmitContext dgc, JScriptWriter staticinit)
        {
            var cls = dgc.Source.ClassDeclaration;
            var ltype = dgc.LType;
            var typename = ltype.CodeName;
            var rtype = ltype.RType;

            staticinit.WriteLine(typename + ".prototype.$static = ");
            staticinit.EnterBlock();

            if (null != ltype.BaseType)
            {
                staticinit.WriteLine("BaseClass: \"" + ltype.BaseType.CodeName + "\",");
            }

            var dplist = new List<DependencyProperty>();

            // emit static variables
            foreach (var fielddecl in cls.ChildNodes().OfType<FieldDeclarationSyntax>())
            {
                foreach (var declarator in fielddecl.DescendantNodes().OfType<VariableDeclaratorSyntax>())
                {
                    var id = declarator.Identifier.ToString();
                    var field = rtype.GetField(id, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

                    if (null != field && field.IsStatic)
                    {
                        if (field.FieldType == typeof(DependencyProperty))
                        {
                            var dp = field.GetValue(null) as DependencyProperty;
                            if (null == dp) continue;
                            dplist.Add(dp);
                        }
                    }
                }
            }

            EmitDependencyPropertyDefinitions(staticinit, dplist);

            staticinit.LeaveBlock();
            staticinit.WriteLine(";");

        }
 private CSharpToJScriptRewriter CreateRewriter(DeclarationEmitContext dgc, IDeclarationContext context = null)
 {
     return new CSharpToJScriptRewriter(dgc, context ?? _context as IDeclarationContext);
 }