Ejemplo n.º 1
0
 public void ASpaceIsInsertedBetweenBinaryAndUnaryPlusAndMinusToAvoidParseAsIncrementOrDecrement()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Identifier("a"), JsExpression.Unary(ExpressionNodeType.Positive, JsExpression.Identifier("b"))), "a+ +b");
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Subtract, JsExpression.Identifier("a"), JsExpression.Unary(ExpressionNodeType.Negate, JsExpression.Identifier("b"))), "a- -b");
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Subtract, JsExpression.Identifier("a"), JsExpression.Unary(ExpressionNodeType.Positive, JsExpression.Identifier("b"))), "a-+b");
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Identifier("a"), JsExpression.Unary(ExpressionNodeType.Negate, JsExpression.Identifier("b"))), "a+-b");
 }
Ejemplo n.º 2
0
        public void ClassWithSameNameAsVariable2()
        {
            var someAsm = Common.CreateMockAssembly();
            var actual  = Process(new JsStatement[] {
                JsStatement.Function("f", new[] { "x" }, JsStatement.Block(
                                         JsStatement.Var("y", JsExpression.Number(0)),
                                         JsExpression.FunctionDefinition(new string[0],
                                                                         JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("x", someAsm)), "a"), JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("y", someAsm)), "a"))
                                                                         ),
                                         JsExpression.FunctionDefinition(new string[0], JsStatement.Block(
                                                                             JsStatement.Var("z", JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Identifier("x"), JsExpression.Identifier("y")))
                                                                             ))
                                         ))
            }, new[] { Common.CreateMockAssembly(), someAsm }, new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(t.Name)
            }, namer: new Namer());

            AssertCorrect(actual,
                          @"(function() {
	'use strict';
	var $asm = {};
	function f(x1) {
		var y1 = 0;
		(function() {
			x.a + y.a;
		});
		(function() {
			var z = x1 + y1;
		});
	}
})();
");
        }
 public void AssignmentIsNotParenthesizedInsideConstructorArgumentList()
 {
     AssertCorrect(JsExpression.ArrayLiteral(
                       JsExpression.Binary(ExpressionNodeType.Assign,
                                           JsExpression.Number(1),
                                           JsExpression.Number(2)
                                           )
                       ),
                   "[1 = 2]");
 }
 public void ExpressionNodeTypeIsNotParenthesizedWhenUsedAsBinaryArgument()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Multiply,
                                       JsExpression.Unary(ExpressionNodeType.Negate,
                                                          JsExpression.Identifier("X")
                                                          ),
                                       JsExpression.Number(1)
                                       ),
                   "-X * 1");
 }
 public void IndexingWorks()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Index,
                                       JsExpression.Binary(ExpressionNodeType.Index,
                                                           JsExpression.Number(1),
                                                           JsExpression.Number(2)
                                                           ),
                                       JsExpression.Number(3)
                                       ),
                   "1[2][3]");
 }
 public void CommaIsNotParenthesizedInsideIndexing()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Index,
                                       JsExpression.Number(1),
                                       JsExpression.Comma(
                                           JsExpression.Number(2),
                                           JsExpression.Number(3)
                                           )
                                       ),
                   "1[2, 3]");
 }
 public void CommaIsParenthesizedAsAssignmentValue()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Assign,
                                       JsExpression.Number(1),
                                       JsExpression.Comma(
                                           JsExpression.Number(2),
                                           JsExpression.Number(3)
                                           )
                                       ),
                   "1 = (2, 3)");
 }
Ejemplo n.º 8
0
        public void ImportingImportedTypeFromOwnAssemblyWorks()
        {
            var asm    = CreateMockAssembly();
            var type   = CreateMockType("MyImportedType", asm);
            var actual = Process(new JsStatement[] {
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(type), "x"), JsExpression.Number(1)))
            }, mainAssembly: asm, metadata: new MockScriptSharpMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType("$" + t.FullName), IsImported = t => ReferenceEquals(t, type)
            });

            AssertCorrect(actual, "return $MyImportedType.x + 1;\n");
        }
 public void ConditionalIsNotDoublyParenthesized()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Add,
                                       JsExpression.Number(1),
                                       JsExpression.Conditional(
                                           JsExpression.Number(2),
                                           JsExpression.Number(3),
                                           JsExpression.Number(4)
                                           )
                                       ),
                   "1 + (2 ? 3 : 4)");
 }
        public void Works()
        {
            var asm = new Mock <IAssembly>(MockBehavior.Strict);

            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(new JsTypeReferenceExpression(asm.Object, "GlobalType")),
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.MemberAccess(new JsTypeReferenceExpression(asm.Object, "Global.NestedNamespace.InnerNamespace.Type"), "x"), JsExpression.Number(1)))
            });

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(
                            @"GlobalType;
return Global.NestedNamespace.InnerNamespace.Type.x + 1;
".Replace("\r\n", "\n")));
        }
Ejemplo n.º 11
0
        public void ImportingTypesFromGlobalNamespaceWorks()
        {
            var otherAsm = CreateMockAssembly();
            var actual   = Process(new JsStatement[] {
                new JsExpressionStatement(new JsTypeReferenceExpression(CreateMockType("GlobalType", otherAsm))),
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(CreateMockType("Global.NestedNamespace.InnerNamespace.Type", otherAsm)), "x"), JsExpression.Number(1)))
            }, metadata: new MockScriptSharpMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(string.Join(".", t.FullName.Split('.').Select(x => "$" + x)))
            });

            AssertCorrect(actual,
                          @"$GlobalType;
return $Global.$NestedNamespace.$InnerNamespace.$Type.x + 1;
");
        }
Ejemplo n.º 12
0
        public void BinaryOperatorsAreCorrectlyOutput()
        {
            var operators = new Dictionary <ExpressionNodeType, string> {
                { ExpressionNodeType.LogicalAnd, "{0}&&{1}" },
                { ExpressionNodeType.LogicalOr, "{0}||{1}" },
                { ExpressionNodeType.NotEqual, "{0}!={1}" },
                { ExpressionNodeType.LesserOrEqual, "{0}<={1}" },
                { ExpressionNodeType.GreaterOrEqual, "{0}>={1}" },
                { ExpressionNodeType.Lesser, "{0}<{1}" },
                { ExpressionNodeType.Greater, "{0}>{1}" },
                { ExpressionNodeType.Equal, "{0}=={1}" },
                { ExpressionNodeType.Subtract, "{0}-{1}" },
                { ExpressionNodeType.Add, "{0}+{1}" },
                { ExpressionNodeType.Modulo, "{0}%{1}" },
                { ExpressionNodeType.Divide, "{0}/{1}" },
                { ExpressionNodeType.Multiply, "{0}*{1}" },
                { ExpressionNodeType.BitwiseAnd, "{0}&{1}" },
                { ExpressionNodeType.BitwiseOr, "{0}|{1}" },
                { ExpressionNodeType.BitwiseXor, "{0}^{1}" },
                { ExpressionNodeType.Same, "{0}==={1}" },
                { ExpressionNodeType.NotSame, "{0}!=={1}" },
                { ExpressionNodeType.LeftShift, "{0}<<{1}" },
                { ExpressionNodeType.RightShiftSigned, "{0}>>{1}" },
                { ExpressionNodeType.RightShiftUnsigned, "{0}>>>{1}" },
                { ExpressionNodeType.InstanceOf, "{0} instanceof {1}" },
                { ExpressionNodeType.In, "{0} in {1}" },
                { ExpressionNodeType.Index, "{0}[{1}]" },
                { ExpressionNodeType.Assign, "{0}={1}" },
                { ExpressionNodeType.MultiplyAssign, "{0}*={1}" },
                { ExpressionNodeType.DivideAssign, "{0}/={1}" },
                { ExpressionNodeType.ModuloAssign, "{0}%={1}" },
                { ExpressionNodeType.AddAssign, "{0}+={1}" },
                { ExpressionNodeType.SubtractAssign, "{0}-={1}" },
                { ExpressionNodeType.LeftShiftAssign, "{0}<<={1}" },
                { ExpressionNodeType.RightShiftSignedAssign, "{0}>>={1}" },
                { ExpressionNodeType.RightShiftUnsignedAssign, "{0}>>>={1}" },
                { ExpressionNodeType.BitwiseAndAssign, "{0}&={1}" },
                { ExpressionNodeType.BitwiseOrAssign, "{0}|={1}" },
                { ExpressionNodeType.BitwiseXorAssign, "{0}^={1}" },
            };

            for (var oper = ExpressionNodeType.BinaryFirst; oper <= ExpressionNodeType.BinaryLast; oper++)
            {
                Assert.That(operators.ContainsKey(oper), string.Format("Unexpected operator {0}", oper));
                var expr = JsExpression.Binary(oper, JsExpression.Identifier("a"), JsExpression.Identifier("b"));
                AssertCorrect(expr, string.Format(operators[oper], "a", "b"));
            }
        }
Ejemplo n.º 13
0
        public void ImportingImportedTypeFromOwnAssemblyWorks()
        {
            var asm    = Common.CreateMockAssembly();
            var type   = Common.CreateMockTypeDefinition("MyImportedType", asm, attributes: new Expression <Func <Attribute> >[] { () => new ImportedAttribute() });
            var actual = Process(new JsStatement[] {
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(type), "x"), JsExpression.Number(1)))
            }, asm, metadata: new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType("$" + t.FullName)
            });

            AssertCorrect(actual,
                          @"(function() {
	return $MyImportedType.x + 1;
})();
");
        }
Ejemplo n.º 14
0
        public void ImportingTypeFromOwnAssemblyUsesTheTypeVariable()
        {
            var asm    = Common.CreateMockAssembly();
            var type   = Common.CreateMockTypeDefinition("GlobalType", asm);
            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(new JsTypeReferenceExpression(type)),
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("Global.NestedNamespace.InnerNamespace.Type", asm)), "x"), JsExpression.Number(1)))
            }, asm, new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(string.Join(".", t.FullName.Split('.').Select(x => "$" + x)))
            });

            AssertCorrect(actual,
                          @"(function() {
	$$GlobalType;
	return $$Global_$NestedNamespace_$InnerNamespace_$Type.x + 1;
})();
");
        }
Ejemplo n.º 15
0
        public void ImportingTypeFromOwnAssemblyButOtherModuleNameResultsInARequire()
        {
            var asm    = Common.CreateMockAssembly(attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("main-module") });
            var type   = Common.CreateMockTypeDefinition("GlobalType", asm, attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("some-module") });
            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(new JsTypeReferenceExpression(type)),
                new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("Global.NestedNamespace.InnerNamespace.Type", asm, attributes: new Expression <Func <Attribute> >[] { () => new ModuleNameAttribute("some-module") })), "x"), JsExpression.Number(1)))
            }, asm, metadata: new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(string.Join(".", t.FullName.Split('.').Select(x => "$" + x)))
            });

            AssertCorrect(actual,
                          @"require('mscorlib');
var $somemodule = require('some-module');
$somemodule.$GlobalType;
return $somemodule.$Global.$NestedNamespace.$InnerNamespace.$Type.x + 1;
");
        }
 public void MultiplicationInConditionalIsParenthesized()
 {
     AssertCorrect(JsExpression.Conditional(
                       JsExpression.Binary(ExpressionNodeType.Multiply,
                                           JsExpression.Number(1),
                                           JsExpression.Number(2)
                                           ),
                       JsExpression.Binary(ExpressionNodeType.Multiply,
                                           JsExpression.Number(3),
                                           JsExpression.Number(4)
                                           ),
                       JsExpression.Binary(ExpressionNodeType.Multiply,
                                           JsExpression.Number(5),
                                           JsExpression.Number(6)
                                           )
                       ),
                   "((1 * 2) ? (3 * 4) : (5 * 6))");
 }
Ejemplo n.º 17
0
        public void ImportingTypesFromGlobalNamespaceWorks()
        {
            var otherAsm = Common.CreateMockAssembly();
            var actual   = Process(new JsStatement[] {
                new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("GlobalType", otherAsm)),
                JsStatement.Return(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("Global.NestedNamespace.InnerNamespace.Type", otherAsm)), "x"), JsExpression.Number(1)))
            }, new[] { Common.CreateMockAssembly(), otherAsm }, new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(string.Join(".", t.FullName.Split('.').Select(x => "$" + x)))
            });

            AssertCorrect(actual,
                          @"(function() {
	'use strict';
	var $asm = {};
	$GlobalType;
	return $Global.$NestedNamespace.$InnerNamespace.$Type.x + 1;
})();
");
        }
        public void LeftToRightAssociativityWorksForExpressionNodeTypes()
        {
            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Subtract,
                                              JsExpression.Binary(ExpressionNodeType.Subtract,
                                                                  JsExpression.Number(1),
                                                                  JsExpression.Number(2)
                                                                  ),
                                              JsExpression.Number(3)
                                              ),
                          "1 - 2 - 3");

            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Subtract,
                                              JsExpression.Number(1),
                                              JsExpression.Binary(ExpressionNodeType.Subtract,
                                                                  JsExpression.Number(2),
                                                                  JsExpression.Number(3)
                                                                  )
                                              ),
                          "1 - (2 - 3)");
        }
Ejemplo n.º 19
0
        public void AsyncModuleWithoutReferencesWorks()
        {
            var asm    = Common.CreateMockAssembly(new Expression <Func <Attribute> >[] { () => new AsyncModuleAttribute() });
            var type   = Common.CreateMockTypeDefinition("GlobalType", asm);
            var actual = Process(new JsStatement[] {
                new JsExpressionStatement(new JsTypeReferenceExpression(type)),
                new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Member(new JsTypeReferenceExpression(Common.CreateMockTypeDefinition("Global.NestedNamespace.InnerNamespace.Type", asm)), "x"), JsExpression.Number(1))),
            }, asm, metadata: new MockMetadataImporter {
                GetTypeSemantics = t => TypeScriptSemantics.NormalType(string.Join(".", t.FullName.Split('.').Select(x => "$" + x)))
            });

            AssertCorrect(actual,
                          @"define(['mscorlib'], function($_) {
	var exports = {};
	$$GlobalType;
	$$Global_$NestedNamespace_$InnerNamespace_$Type.x + 1;
	return exports;
});
");
        }
        public void RightToLeftAssociativityWorksForExpressionNodeTypes()
        {
            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Assign,
                                              JsExpression.Number(1),
                                              JsExpression.Binary(ExpressionNodeType.Assign,
                                                                  JsExpression.Number(2),
                                                                  JsExpression.Number(3)
                                                                  )
                                              ),
                          "1 = 2 = 3");

            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Assign,
                                              JsExpression.Binary(ExpressionNodeType.Assign,
                                                                  JsExpression.Number(1),
                                                                  JsExpression.Number(2)
                                                                  ),
                                              JsExpression.Number(3)
                                              ),
                          "(1 = 2) = 3");
        }
        public void MultiplyHasHigherPrecedenceThanAdd()
        {
            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Add,
                                              JsExpression.Binary(ExpressionNodeType.Multiply,
                                                                  JsExpression.Number(1),
                                                                  JsExpression.Number(2)
                                                                  ),
                                              JsExpression.Number(3)
                                              ),
                          "1 * 2 + 3");

            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Add,
                                              JsExpression.Number(1),
                                              JsExpression.Binary(ExpressionNodeType.Multiply,
                                                                  JsExpression.Number(2),
                                                                  JsExpression.Number(3)
                                                                  )
                                              ),
                          "1 + 2 * 3");

            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Multiply,
                                              JsExpression.Binary(ExpressionNodeType.Add,
                                                                  JsExpression.Number(1),
                                                                  JsExpression.Number(2)
                                                                  ),
                                              JsExpression.Number(3)
                                              ),
                          "(1 + 2) * 3");

            AssertCorrect(JsExpression.Binary(ExpressionNodeType.Multiply,
                                              JsExpression.Number(1),
                                              JsExpression.Binary(ExpressionNodeType.Add,
                                                                  JsExpression.Number(2),
                                                                  JsExpression.Number(3)
                                                                  )
                                              ),
                          "1 * (2 + 3)");
        }
Ejemplo n.º 22
0
        public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint)
        {
            var result = new List <JsStatement>();

            var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList();

            foreach (var t in orderedTypes)
            {
                try {
                    string name     = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name;
                    bool   isGlobal = string.IsNullOrEmpty(name);
                    bool   isMixin  = MetadataUtils.IsMixin(t.CSharpTypeDefinition);

                    result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name));
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (isGlobal)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition))));
                        }
                        else if (isMixin)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))));
                        }
                        else if (MetadataUtils.IsResources(c.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);

                            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
                            {
                                var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList();
                                var stmts = new List <JsStatement> {
                                    new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName));
                                for (int i = 0; i < stmts.Count; i++)
                                {
                                    stmts[i] = replacer.Process(stmts[i]);
                                }
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(typeParameterNames, new JsBlockStatement(stmts))));
                                var args = new List <JsExpression> {
                                    GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount)
                                };
                                var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false);
                                if (metadata != null)
                                {
                                    args.Add(metadata);
                                }
                                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterface : RegisterGenericClass), args)));
                            }
                            else
                            {
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor));
                                AddClassMembers(c, typeRef, result);
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var e = (JsEnum)t;
                        result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)));
                        var values = new List <JsObjectLiteralProperty>();
                        foreach (var v in e.CSharpTypeDefinition.Fields)
                        {
                            if (v.ConstantValue != null)
                            {
                                var sem = _metadataImporter.GetFieldSemantics(v);
                                if (sem.Type == FieldScriptSemantics.ImplType.Field)
                                {
                                    values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue))));
                                }
                                else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null)
                                {
                                    values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value))));
                                }
                            }
                            else
                            {
                                _errorReporter.Region = v.Region;
                                _errorReporter.InternalError("Enum field " + v.FullName + " is not constant.");
                            }
                        }
                        result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(values))));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            var typesToRegister = orderedTypes
                                  .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) &&
                                         !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) &&
                                         (!MetadataUtils.IsResources(c.CSharpTypeDefinition) || c.CSharpTypeDefinition.IsExternallyVisible()) &&                        // Resources classes are only exported if they are public.
                                         !MetadataUtils.IsMixin(c.CSharpTypeDefinition))
                                  .ToList();

            result.AddRange(TopologicalSortTypesByInheritance(typesToRegister)
                            .Select(c => {
                try {
                    string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name;
                    if (c.CSharpTypeDefinition.Kind == TypeKind.Enum)
                    {
                        return(CreateRegisterEnumCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                    }
                    if (MetadataUtils.IsResources(c.CSharpTypeDefinition))
                    {
                        return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                    }
                    if (c.CSharpTypeDefinition.Kind == TypeKind.Interface)
                    {
                        return(CreateRegisterInterfaceCall(c.CSharpTypeDefinition,
                                                           name,
                                                           JsExpression.Identifier(_namer.GetTypeVariableName(name)),
                                                           GetImplementedInterfaces(c.CSharpTypeDefinition.GetDefinition()).ToList()));
                    }
                    else
                    {
                        return(CreateRegisterClassCall(c.CSharpTypeDefinition,
                                                       name,
                                                       JsExpression.Identifier(_namer.GetTypeVariableName(name)),
                                                       GetBaseClass(c.CSharpTypeDefinition),
                                                       GetImplementedInterfaces(c.CSharpTypeDefinition).ToList()));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = c.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName);
                    return(JsExpression.Number(0));
                }
            })
                            .Select(expr => new JsExpressionStatement(expr)));
            result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1)
                            .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition))
                            .SelectMany(c => c.StaticInitStatements));

            if (entryPoint != null)
            {
                if (entryPoint.Parameters.Count > 0)
                {
                    _errorReporter.Region = entryPoint.Region;
                    _errorReporter.Message(Messages._7800, entryPoint.FullName);
                }
                else
                {
                    var sem = _metadataImporter.GetMethodSemantics(entryPoint);
                    if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod)
                    {
                        _errorReporter.Region = entryPoint.Region;
                        _errorReporter.Message(Messages._7801, entryPoint.FullName);
                    }
                    else
                    {
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))));
                    }
                }
            }

            return(result);
        }
        public IList <JsStatement> Rewrite(IEnumerable <JsType> types, ICompilation compilation)
        {
            var netSystemType = compilation.FindType(KnownTypeCode.Type).GetDefinition();
            var systemType    = new JsTypeReferenceExpression(netSystemType.ParentAssembly, _metadataImporter.GetTypeSemantics(netSystemType).Name);

            var result = new List <JsStatement>();

            var    orderedTypes = OrderByNamespace(types, t => t.Name).ToList();
            string currentNs    = "";

            foreach (var t in orderedTypes)
            {
                try {
                    var globalMethodsPrefix = _metadataImporter.GetGlobalMethodsPrefix(t.CSharpTypeDefinition);

                    string ns = GetNamespace(t.Name);
                    if (ns != currentNs && globalMethodsPrefix == null)
                    {
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(systemType, RegisterNamespace), JsExpression.String(ns))));
                        currentNs = ns;
                    }
                    result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, t.Name);
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (globalMethodsPrefix != null)
                        {
                            if (globalMethodsPrefix == "")
                            {
                                result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.MemberAccess(JsExpression.Identifier("window"), m.Name), m.Definition))));
                            }
                            else
                            {
                                result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(globalMethodsPrefix + "." + m.Name), m.Definition))));
                            }
                        }
                        else if (_metadataImporter.IsResources(t.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);

                            if (c.TypeArgumentNames.Count == 0)
                            {
                                result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, unnamedCtor)));
                                AddClassMembers(c, typeRef, compilation, result);
                            }
                            else
                            {
                                var stmts = new List <JsStatement> {
                                    new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), compilation, stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(c.TypeArgumentNames, new JsBlockStatement(stmts)))));
                                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, c.ClassType == JsClass.ClassTypeEnum.Interface ? RegisterGenericInterface : RegisterGenericClass), JsExpression.String(c.Name), JsExpression.Number(c.TypeArgumentNames.Count))));
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var  e     = (JsEnum)t;
                        bool flags = GetAttributePositionalArgs(t.CSharpTypeDefinition, FlagsAttribute, "System") != null;
                        result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement))));
                        result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, Prototype), JsExpression.ObjectLiteral(e.Values.Select(v => new JsObjectLiteralProperty(v.Name, (_metadataImporter.IsNamedValues(t.CSharpTypeDefinition) ? JsExpression.String(v.Name) : JsExpression.Number(v.Value))))))));
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterEnum), JsExpression.String(t.Name), JsExpression.Boolean(flags))));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            var typesToRegister = orderedTypes.OfType <JsClass>()
                                  .Where(c => c.TypeArgumentNames.Count == 0 &&
                                         _metadataImporter.GetGlobalMethodsPrefix(c.CSharpTypeDefinition) == null &&
                                         !_metadataImporter.IsResources(c.CSharpTypeDefinition))
                                  .ToList();

            result.AddRange(TopologicalSortTypesByInheritance(typesToRegister)
                            .Select(c => {
                try {
                    var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, c.Name);
                    if (c.ClassType == JsClass.ClassTypeEnum.Interface)
                    {
                        return(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterInterface), JsExpression.String(c.Name), JsExpression.ArrayLiteral(c.ImplementedInterfaces)));
                    }
                    else
                    {
                        return(CreateRegisterClassCall(JsExpression.String(c.Name), c.BaseClass, c.ImplementedInterfaces, typeRef));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = c.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName);
                    return(JsExpression.Number(0));
                }
            })
                            .Select(expr => new JsExpressionStatement(expr)));
            result.AddRange(orderedTypes.OfType <JsClass>().Where(c => c.TypeArgumentNames.Count == 0 && !_metadataImporter.IsResources(c.CSharpTypeDefinition)).SelectMany(t => t.StaticInitStatements));

            return(result);
        }
Ejemplo n.º 24
0
        public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint)
        {
            var result = new List <JsStatement>();

            var orderedTypes             = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList();
            var exportedNamespacesByRoot = new Dictionary <string, HashSet <string> >();

            foreach (var t in orderedTypes)
            {
                try {
                    string name     = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name;
                    bool   isGlobal = string.IsNullOrEmpty(name);
                    bool   isMixin  = MetadataUtils.IsMixin(t.CSharpTypeDefinition);
                    bool   export   = t.CSharpTypeDefinition.IsExternallyVisible();

                    result.Add(JsStatement.Comment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    string typevarName = _namer.GetTypeVariableName(name);
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (isGlobal)
                        {
                            result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(JsExpression.Identifier(GetRoot(t.CSharpTypeDefinition)), m.Name), m.Definition)));
                            export = false;
                        }
                        else if (isMixin)
                        {
                            result.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition)));
                            export = false;
                        }
                        else if (MetadataUtils.IsResources(c.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock);

                            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
                            {
                                var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList();
                                var stmts = new List <JsStatement> {
                                    JsStatement.Var(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, InstantiatedGenericTypeVariableName, stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(JsStatement.Return(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName));
                                for (int i = 0; i < stmts.Count; i++)
                                {
                                    stmts[i] = replacer.Process(stmts[i]);
                                }
                                result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(typeParameterNames, JsStatement.Block(stmts))));
                                result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name)));
                                var args = new List <JsExpression> {
                                    JsExpression.Identifier(typevarName), JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount)
                                };
                                result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? InitGenericInterface : InitGenericClass), args));
                            }
                            else
                            {
                                result.Add(JsStatement.Var(typevarName, unnamedCtor));
                                result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name)));
                                AddClassMembers(c, typevarName, result);
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var e = (JsEnum)t;
                        result.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock)));
                        result.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(e.CSharpTypeDefinition).Name)));
                    }

                    if (export)
                    {
                        string root  = GetRoot(t.CSharpTypeDefinition);
                        var    split = SplitIntoNamespaceAndName(name);
                        if (!string.IsNullOrEmpty(split.Item1))
                        {
                            HashSet <string> hs;
                            if (!exportedNamespacesByRoot.TryGetValue(root, out hs))
                            {
                                hs = exportedNamespacesByRoot[root] = new HashSet <string>();
                            }
                            hs.Add(split.Item1);
                        }

                        result.Add(JsExpression.Assign(MakeNestedMemberAccess(name, JsExpression.Identifier(root)), JsExpression.Identifier(typevarName)));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            result.InsertRange(0, exportedNamespacesByRoot.OrderBy(x => x.Key).SelectMany(x => CreateNamespaces(JsExpression.Identifier(x.Key), x.Value)).ToList());

            var typesToRegister = TopologicalSortTypesByInheritance(orderedTypes)
                                  .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) &&
                                         !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) &&
                                         !MetadataUtils.IsResources(c.CSharpTypeDefinition) &&
                                         !MetadataUtils.IsMixin(c.CSharpTypeDefinition))
                                  .ToList();

            foreach (var t in typesToRegister)
            {
                try {
                    string name        = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name;
                    string typevarName = _namer.GetTypeVariableName(name);
                    if (t.CSharpTypeDefinition.Kind == TypeKind.Enum)
                    {
                        result.Add(CreateInitEnumCall((JsEnum)t, typevarName));
                    }
                    else
                    {
                        var c = (JsClass)t;
                        if (t.CSharpTypeDefinition.Kind == TypeKind.Interface)
                        {
                            result.Add(CreateInitInterfaceCall(c, typevarName, GetImplementedInterfaces(t.CSharpTypeDefinition.GetDefinition()).ToList()));
                        }
                        else
                        {
                            result.Add(CreateInitClassCall(c, typevarName, GetBaseClass(t.CSharpTypeDefinition), GetImplementedInterfaces(t.CSharpTypeDefinition).ToList()));
                            if (c.NamedConstructors.Count > 0)
                            {
                                result.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                            }
                        }
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            foreach (var t in orderedTypes)
            {
                var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false);
                if (metadata != null)
                {
                    result.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(_namer.GetTypeVariableName(_metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name)), metadata));
                }
            }

            result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1)
                            .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition))
                            .SelectMany(c => c.StaticInitStatements));

            if (entryPoint != null)
            {
                if (entryPoint.Parameters.Count > 0)
                {
                    _errorReporter.Region = entryPoint.Region;
                    _errorReporter.Message(Messages._7800, entryPoint.FullName);
                }
                else
                {
                    var sem = _metadataImporter.GetMethodSemantics(entryPoint);
                    if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod)
                    {
                        _errorReporter.Region = entryPoint.Region;
                        _errorReporter.Message(Messages._7801, entryPoint.FullName);
                    }
                    else
                    {
                        result.Add(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name)));
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 25
0
        private TypeOOPEmulationPhase CreateTypeDefinitions(JsType type)
        {
            string name       = _metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name;
            bool   isGlobal   = string.IsNullOrEmpty(name);
            bool   isMixin    = MetadataUtils.IsMixin(type.CSharpTypeDefinition, _attributeStore);
            bool   export     = type.CSharpTypeDefinition.IsExternallyVisible();
            var    statements = new List <JsStatement>();

            statements.Add(JsStatement.Comment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + type.CSharpTypeDefinition.FullName));

            string typevarName = _namer.GetTypeVariableName(name);

            if (type is JsClass)
            {
                var c = (JsClass)type;
                if (isGlobal)
                {
                    statements.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(JsExpression.Identifier(GetRoot(type.CSharpTypeDefinition)), m.Name), m.Definition)));
                    export = false;
                }
                else if (isMixin)
                {
                    statements.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition)));
                    export = false;
                }
                else if (MetadataUtils.IsResources(c.CSharpTypeDefinition, _attributeStore))
                {
                    statements.Add(GenerateResourcesClass(c));
                }
                else
                {
                    var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock);

                    if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
                    {
                        var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList();
                        var stmts = new List <JsStatement> {
                            JsStatement.Var(InstantiatedGenericTypeVariableName, unnamedCtor)
                        };
                        AddClassMembers(c, InstantiatedGenericTypeVariableName, stmts);
                        stmts.AddRange(c.StaticInitStatements);
                        stmts.Add(JsStatement.Return(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                        var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName));
                        for (int i = 0; i < stmts.Count; i++)
                        {
                            stmts[i] = replacer.Process(stmts[i]);
                        }
                        statements.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(typeParameterNames, JsStatement.Block(stmts))));
                        statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name)));
                        var args = new List <JsExpression> {
                            JsExpression.Identifier(typevarName), _linker.CurrentAssemblyExpression, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount)
                        };
                        statements.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? InitGenericInterface : InitGenericClass), args));
                    }
                    else
                    {
                        statements.Add(JsStatement.Var(typevarName, unnamedCtor));
                        statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name)));
                        AddClassMembers(c, typevarName, statements);
                    }
                }
            }
            else if (type is JsEnum)
            {
                var e = (JsEnum)type;
                statements.Add(JsStatement.Var(typevarName, JsExpression.FunctionDefinition(new string[0], JsStatement.EmptyBlock)));
                statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), TypeName), JsExpression.String(_metadataImporter.GetTypeSemantics(e.CSharpTypeDefinition).Name)));
            }

            if (export)
            {
                string root = GetRoot(type.CSharpTypeDefinition);
                statements.Add(JsExpression.Assign(MakeNestedMemberAccess(name, JsExpression.Identifier(root)), JsExpression.Identifier(typevarName)));
            }

            return(new TypeOOPEmulationPhase(null, statements));
        }
        public virtual JsExpression VisitBinaryExpression(JsBinaryExpression expression, TData data)
        {
            var left  = VisitExpression(expression.Left, data);
            var right = VisitExpression(expression.Right, data);

            return(ReferenceEquals(left, expression.Left) && ReferenceEquals(right, expression.Right) ? expression : JsExpression.Binary(expression.NodeType, left, right));
        }
Ejemplo n.º 27
0
        public void TheOverallStructureIsCorrect()
        {
            AssertCorrect(
                @"////////////////////////////////////////////////////////////////////////////////
// OuterNamespace.InnerNamespace.SomeEnum
var $OuterNamespace_InnerNamespace_SomeEnum = function() {
};
$OuterNamespace_InnerNamespace_SomeEnum.prototype = { Value1: 1, Value2: 2, Value3: 3 };
{Type}.registerEnum(global, 'OuterNamespace.InnerNamespace.SomeEnum', $OuterNamespace_InnerNamespace_SomeEnum, false);
////////////////////////////////////////////////////////////////////////////////
// OuterNamespace.InnerNamespace.SomeType
var $OuterNamespace_InnerNamespace_SomeType = function() {
	this.a = 0;
};
$OuterNamespace_InnerNamespace_SomeType.prototype = {
	method1: function(x) {
		return x;
	},
	method2: function(x, y) {
		return x + y;
	}
};
$OuterNamespace_InnerNamespace_SomeType.staticMethod = function() {
};
////////////////////////////////////////////////////////////////////////////////
// OuterNamespace.InnerNamespace.SomeType2
var $OuterNamespace_InnerNamespace_SomeType2 = function() {
	this.b = 0;
};
$OuterNamespace_InnerNamespace_SomeType2.prototype = {
	method1: function(x) {
		return x;
	}
};
$OuterNamespace_InnerNamespace_SomeType2.otherStaticMethod = function() {
};
////////////////////////////////////////////////////////////////////////////////
// OuterNamespace.InnerNamespace2.OtherInterface
var $OuterNamespace_InnerNamespace2_OtherInterface = function() {
};
$OuterNamespace_InnerNamespace2_OtherInterface.prototype = { interfaceMethod: null };
////////////////////////////////////////////////////////////////////////////////
// OuterNamespace.InnerNamespace2.OtherType
var $OuterNamespace_InnerNamespace2_OtherType = function() {
};
$OuterNamespace_InnerNamespace2_OtherType.prototype = {
	method1: function(x) {
		return x;
	}
};
{Type}.registerClass(global, 'OuterNamespace.InnerNamespace.SomeType', $OuterNamespace_InnerNamespace_SomeType);
{Type}.registerClass(global, 'OuterNamespace.InnerNamespace.SomeType2', $OuterNamespace_InnerNamespace_SomeType2);
{Type}.registerInterface(global, 'OuterNamespace.InnerNamespace2.OtherInterface', $OuterNamespace_InnerNamespace2_OtherInterface, []);
{Type}.registerClass(global, 'OuterNamespace.InnerNamespace2.OtherType', $OuterNamespace_InnerNamespace2_OtherType, {SomeType2});
y = 1;
x = 1;
",

                new JsClass(CreateMockTypeDefinition("OuterNamespace.InnerNamespace.SomeType"), JsClass.ClassTypeEnum.Class, null, null, null)
            {
                UnnamedConstructor = JsExpression.FunctionDefinition(new string[0], new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(JsExpression.This, "a"), JsExpression.Number(0)))),
                InstanceMethods    = { new JsMethod(CreateMockMethod("Method1"), "method1", null, JsExpression.FunctionDefinition(new[] { "x" }, new JsReturnStatement(JsExpression.Identifier("x")))),
                                       new JsMethod(CreateMockMethod("Method2"),    "method2", null, JsExpression.FunctionDefinition(new[] { "x", "y"}, new JsReturnStatement(JsExpression.Binary(ExpressionNodeType.Add, JsExpression.Identifier("x"), JsExpression.Identifier("y"))))) },
                StaticMethods = { new JsMethod(CreateMockMethod("StaticMethod"), "staticMethod", null, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)) },
            },
                new JsClass(CreateMockTypeDefinition("OuterNamespace.InnerNamespace.SomeType2"), JsClass.ClassTypeEnum.Class, null, null, null)
            {
                UnnamedConstructor   = JsExpression.FunctionDefinition(new string[0], new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(JsExpression.This, "b"), JsExpression.Number(0)))),
                InstanceMethods      = { new JsMethod(CreateMockMethod("Method1"), "method1", null, JsExpression.FunctionDefinition(new[] { "x" }, new JsReturnStatement(JsExpression.Identifier("x")))) },
                StaticMethods        = { new JsMethod(CreateMockMethod("OtherStaticMethod"), "otherStaticMethod", null, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)) },
                StaticInitStatements = { new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("y"), JsExpression.Number(1))) }
            },
                new JsEnum(CreateMockTypeDefinition("OuterNamespace.InnerNamespace.SomeEnum"), new[] {
                new JsEnumValue("Value1", 1),
                new JsEnumValue("Value2", 2),
                new JsEnumValue("Value3", 3),
            }),
                new JsClass(CreateMockTypeDefinition("OuterNamespace.InnerNamespace2.OtherType"), JsClass.ClassTypeEnum.Class, null, new JsTypeReferenceExpression(Common.CreateMockType("OuterNamespace.InnerNamespace.SomeType2")), null)
            {
                UnnamedConstructor   = JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement),
                InstanceMethods      = { new JsMethod(CreateMockMethod("Method1"), "method1", null, JsExpression.FunctionDefinition(new[] { "x" }, new JsReturnStatement(JsExpression.Identifier("x")))), },
                StaticInitStatements = { new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("x"), JsExpression.Number(1))) }
            },
                new JsClass(CreateMockTypeDefinition("OuterNamespace.InnerNamespace2.OtherInterface"), JsClass.ClassTypeEnum.Interface, null, null, null)
            {
                UnnamedConstructor   = JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement),
                InstanceMethods      = { new JsMethod(CreateMockMethod("InterfaceMethod"), "interfaceMethod", null, null) },
                StaticInitStatements = {}
            });
        }
        public IList <JsStatement> Process(IEnumerable <JsType> types, ICompilation compilation, IMethod entryPoint)
        {
            var result = new List <JsStatement>();

            var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList();

            foreach (var t in orderedTypes)
            {
                try {
                    string name     = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name;
                    bool   isGlobal = string.IsNullOrEmpty(name);
                    bool   isMixin  = _metadataImporter.IsMixin(t.CSharpTypeDefinition);

                    result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name));
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (isGlobal)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition))));
                        }
                        else if (isMixin)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))));
                        }
                        else if (_metadataImporter.IsResources(t.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);

                            if (c.TypeArgumentNames.Count == 0)
                            {
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor));
                                AddClassMembers(c, typeRef, compilation, result);
                            }
                            else
                            {
                                var stmts = new List <JsStatement> {
                                    new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), compilation, stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(c.TypeArgumentNames, new JsBlockStatement(stmts))));
                                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemType, c.ClassType == JsClass.ClassTypeEnum.Interface ? RegisterGenericInterface : RegisterGenericClass), GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.TypeArgumentNames.Count))));
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var  e     = (JsEnum)t;
                        bool flags = GetAttributePositionalArgs(t.CSharpTypeDefinition, FlagsAttribute, "System") != null;
                        result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)));
                        result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(e.Values.Select(v => new JsObjectLiteralProperty(v.Name, (_metadataImporter.IsNamedValues(t.CSharpTypeDefinition) ? JsExpression.String(v.Name) : JsExpression.Number(v.Value))))))));
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterEnum), GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Boolean(flags))));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            var typesToRegister = orderedTypes.OfType <JsClass>()
                                  .Where(c => c.TypeArgumentNames.Count == 0 &&
                                         !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) &&
                                         (!_metadataImporter.IsResources(c.CSharpTypeDefinition) || Utils.IsPublic(c.CSharpTypeDefinition)) &&                          // Resources classes are only exported if they are public.
                                         !_metadataImporter.IsMixin(c.CSharpTypeDefinition))
                                  .ToList();

            result.AddRange(TopologicalSortTypesByInheritance(typesToRegister)
                            .Select(c => {
                try {
                    string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name;
                    if (_metadataImporter.IsResources(c.CSharpTypeDefinition))
                    {
                        return(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                    }
                    if (c.ClassType == JsClass.ClassTypeEnum.Interface)
                    {
                        return(JsExpression.Invocation(JsExpression.Member(_systemType, RegisterInterface), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name)), JsExpression.ArrayLiteral(c.ImplementedInterfaces)));
                    }
                    else
                    {
                        return(CreateRegisterClassCall(GetRoot(c.CSharpTypeDefinition), name, JsExpression.Identifier(_namer.GetTypeVariableName(name)), c.BaseClass, c.ImplementedInterfaces));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = c.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName);
                    return(JsExpression.Number(0));
                }
            })
                            .Select(expr => new JsExpressionStatement(expr)));
            result.AddRange(orderedTypes.OfType <JsClass>().Where(c => c.TypeArgumentNames.Count == 0 && !_metadataImporter.IsResources(c.CSharpTypeDefinition)).SelectMany(t => t.StaticInitStatements));

            if (entryPoint != null)
            {
                if (entryPoint.Parameters.Count > 0)
                {
                    _errorReporter.Region = entryPoint.Region;
                    _errorReporter.Message(7800, entryPoint.FullName);
                }
                else
                {
                    var sem = _metadataImporter.GetMethodSemantics(entryPoint);
                    if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod)
                    {
                        _errorReporter.Region = entryPoint.Region;
                        _errorReporter.Message(7801, entryPoint.FullName);
                    }
                    else
                    {
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))));
                    }
                }
            }

            return(result);
        }