示例#1
0
 public void TryCatchFinallyStatementWithCatchOrFinallyOrBothIsCorrectlyOutput()
 {
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), JsStatement.Catch("e", JsExpression.Identifier("y")), JsExpression.Identifier("z")),
                   "try {\n\tx;\n}\ncatch (e) {\n\ty;\n}\nfinally {\n\tz;\n}\n");
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), JsStatement.Catch("e", JsExpression.Identifier("y")), null),
                   "try {\n\tx;\n}\ncatch (e) {\n\ty;\n}\n");
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), null, JsExpression.Identifier("z")),
                   "try {\n\tx;\n}\nfinally {\n\tz;\n}\n");
 }
 public void SwitchStatementWorks()
 {
     AssertCorrect(JsStatement.Switch(JsExpression.Identifier("x"),
                                      JsStatement.SwitchSection(new[] { JsExpression.Number(0) }, JsExpression.Identifier("a")),
                                      JsStatement.SwitchSection(new[] { JsExpression.Number(1), JsExpression.Number(2) }, JsExpression.Identifier("b")),
                                      JsStatement.SwitchSection(new[] { null, JsExpression.Number(3) }, JsExpression.Identifier("c"))
                                      ),
                   "switch(x){case 0:{a;}case 1:case 2:{b;}default:case 3:{c;}}");
 }
 public void TryCatchFinallyStatementWithCatchOrFinallyOrBothWorks()
 {
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), JsStatement.Catch("e", JsExpression.Identifier("y")), JsExpression.Identifier("z")),
                   "try{x;}catch(e){y;}finally{z;}");
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), JsStatement.Catch("e", JsExpression.Identifier("y")), null),
                   "try{x;}catch(e){y;}");
     AssertCorrect(JsStatement.Try(JsExpression.Identifier("x"), null, JsExpression.Identifier("z")),
                   "try{x;}finally{z;}");
 }
 public void IfAndElseIfStatementsAreChained()
 {
     AssertCorrect(JsStatement.If(JsExpression.True, JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0)), null),
                   "if(true){i=0;}");
     AssertCorrect(JsStatement.If(JsExpression.Identifier("a"), JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0)),
                                  JsStatement.If(JsExpression.Identifier("b"), JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(1)),
                                                 JsStatement.If(JsExpression.Identifier("c"), JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(2)), JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(3))))),
                   "if(a){i=0;}else if(b){i=1;}else if(c){i=2;}else{i=3;}");
 }
示例#5
0
 public void TryCatchFinallyStatementWithCatchOrFinallyOrBothWorks()
 {
     AssertCorrect(new JsTryStatement(new JsExpressionStatement(JsExpression.Identifier("x")), new JsCatchClause("e", new JsExpressionStatement(JsExpression.Identifier("y"))), new JsExpressionStatement(JsExpression.Identifier("z"))),
                   "try{x;}catch(e){y;}finally{z;}");
     AssertCorrect(new JsTryStatement(new JsExpressionStatement(JsExpression.Identifier("x")), new JsCatchClause("e", new JsExpressionStatement(JsExpression.Identifier("y"))), null),
                   "try{x;}catch(e){y;}");
     AssertCorrect(new JsTryStatement(new JsExpressionStatement(JsExpression.Identifier("x")), null, new JsExpressionStatement(JsExpression.Identifier("z"))),
                   "try{x;}finally{z;}");
 }
 public void IncrementIsParenthesizedWhenUsedAsInvocationMethod()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Unary(ExpressionNodeType.PostfixMinusMinus,
                                          JsExpression.Identifier("x")
                                          ),
                       new JsExpression[0]
                       ),
                   "(x--)()");
 }
 public void IncrementIsParenthesizedWhenBeingUsedAsInvocationTarget()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Unary(ExpressionNodeType.PostfixPlusPlus,
                                          JsExpression.Identifier("X")
                                          ),
                       new[] { JsExpression.Number(1) }
                       ),
                   "(X++)(1)");
 }
 public void ExpressionNodeTypeIsNotParenthesizedWhenUsedAsBinaryArgument()
 {
     AssertCorrect(JsExpression.Binary(ExpressionNodeType.Multiply,
                                       JsExpression.Unary(ExpressionNodeType.Negate,
                                                          JsExpression.Identifier("X")
                                                          ),
                                       JsExpression.Number(1)
                                       ),
                   "-X * 1");
 }
        private TypeOOPEmulationPhase CreateInitTypeCalls(JsType type)
        {
            bool generateCall = true;

            if (type is JsClass && MetadataUtils.IsJsGeneric(type.CSharpTypeDefinition, _metadataImporter))
            {
                generateCall = false;
            }
            if (string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name))
            {
                generateCall = false;
            }
            if (MetadataUtils.IsResources(type.CSharpTypeDefinition, _attributeStore))
            {
                generateCall = false;
            }
            if (MetadataUtils.IsMixin(type.CSharpTypeDefinition, _attributeStore))
            {
                generateCall = false;
            }

            var statements = new List <JsStatement>();

            if (generateCall)
            {
                string name        = _metadataImporter.GetTypeSemantics(type.CSharpTypeDefinition).Name;
                string typevarName = _namer.GetTypeVariableName(name);
                if (type.CSharpTypeDefinition.Kind == TypeKind.Enum)
                {
                    statements.Add(CreateInitEnumCall((JsEnum)type, typevarName));
                }
                else
                {
                    var c = (JsClass)type;
                    if (type.CSharpTypeDefinition.Kind == TypeKind.Interface)
                    {
                        statements.Add(CreateInitInterfaceCall(c, typevarName, GetImplementedInterfaces(type.CSharpTypeDefinition.GetDefinition()).ToList()));
                    }
                    else
                    {
                        statements.Add(CreateInitClassCall(c, typevarName, GetBaseClass(type.CSharpTypeDefinition), GetImplementedInterfaces(type.CSharpTypeDefinition).ToList()));
                        if (c.NamedConstructors.Count > 0)
                        {
                            statements.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                        }
                        if (c.CSharpTypeDefinition.Kind == TypeKind.Struct)
                        {
                            statements.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(_namer.GetTypeVariableName(name)), "__class"), JsExpression.False));
                        }
                    }
                }
            }

            return(new TypeOOPEmulationPhase(type.CSharpTypeDefinition.GetAllBaseTypeDefinitions().Where(t => !t.Equals(type.CSharpTypeDefinition)), statements));
        }
 private JsExpression GetRoot(ITypeDefinition type, bool exportNonPublic = false)
 {
     if (!exportNonPublic && !Utils.IsPublic(type))
     {
         return(JsExpression.Null);
     }
     else
     {
         return(JsExpression.Identifier(string.IsNullOrEmpty(_metadataImporter.GetModuleName(type)) ? "global" : "exports"));
     }
 }
            public override JsExpression VisitTypeReferenceExpression(JsTypeReferenceExpression expression, object data)
            {
                var          parts  = expression.TypeName.Split('.');
                JsExpression result = JsExpression.Identifier(parts[0]);

                for (int i = 1; i < parts.Length; i++)
                {
                    result = JsExpression.MemberAccess(result, parts[i]);
                }
                return(result);
            }
示例#12
0
        public void GenericClassWorks()
        {
            AssertCorrect(
                @"{Type}.registerNamespace('SomeNamespace.InnerNamespace');
////////////////////////////////////////////////////////////////////////////////
// SomeNamespace.InnerNamespace.MyClass
{MyClass} = function(T1, T2) {
	var $type = function(x) {
		X;
	};
	$type.prototype = {
		m1: function(a) {
			A;
		},
		m2: function(b) {
			B;
		}
	};
	$type.ctor1 = function(y) {
		Y;
	};
	$type.ctor2 = function(z) {
		Z;
	};
	$type.ctor1.prototype = $type.ctor2.prototype = $type.prototype;
	$type.s1 = function(s) {
		S;
	};
	$type.s2 = function(t) {
		T;
	};
	$type.registerGenericClassInstance($type, {MyClass}, [T1, T2], function() {
		return $InstantiateGenericType(TheBaseClass, T1);
	}, function() {
		return [Interface1, $InstantiateGenericType(Interface2, T2, Int32), Interface3];
	});
	Q;
	R;
	return $type;
};
{MyClass}.registerGenericClass('SomeNamespace.InnerNamespace.MyClass', 2);
", new JsClass(CreateMockType("SomeNamespace.InnerNamespace.MyClass"), "SomeNamespace.InnerNamespace.MyClass", JsClass.ClassTypeEnum.Class, new[] { "T1", "T2" }, JsExpression.Invocation(JsExpression.Identifier("$InstantiateGenericType"), JsExpression.Identifier("TheBaseClass"), JsExpression.Identifier("T1")), new JsExpression[] { JsExpression.Identifier("Interface1"), JsExpression.Invocation(JsExpression.Identifier("$InstantiateGenericType"), JsExpression.Identifier("Interface2"), JsExpression.Identifier("T2"), JsExpression.Identifier("Int32")), JsExpression.Identifier("Interface3") })
            {
                UnnamedConstructor = CreateFunction("x"),
                NamedConstructors  = { new JsNamedConstructor("ctor1", CreateFunction("y")),
                                       new JsNamedConstructor("ctor2",  CreateFunction("z")), },
                InstanceMethods = { new JsMethod(CreateMockMethod("M1"), "m1", null, CreateFunction("a")),
                                    new JsMethod(CreateMockMethod("M2"), "m2", null, CreateFunction("b")), },
                StaticMethods = { new JsMethod(CreateMockMethod("S1"), "s1", null, CreateFunction("s")),
                                  new JsMethod(CreateMockMethod("S2"), "s2", null, CreateFunction("t")) },
                StaticInitStatements = { new JsExpressionStatement(JsExpression.Identifier("Q")),
                                         new JsExpressionStatement(JsExpression.Identifier("R")), }
            });
        }
示例#13
0
 private JsExpression GetRoot(ITypeDefinition type, bool exportNonPublic = false)
 {
     if (!exportNonPublic && !type.IsExternallyVisible())
     {
         return(JsExpression.Null);
     }
     else
     {
         return(JsExpression.Identifier(string.IsNullOrEmpty(MetadataUtils.GetModuleName(type)) ? "global" : "exports"));
     }
 }
示例#14
0
 public JsExpression ResolveTypeParameter(ITypeParameter tp)
 {
     if (_isGenericSpecialization && tp.OwnerType == EntityType.TypeDefinition)
     {
         return(JsExpression.Identifier(_namer.GetTypeParameterName(tp)));
     }
     else
     {
         return(_systemObject);
     }
 }
示例#15
0
        private JsExpression MakeNestedMemberAccess(string full)
        {
            var          parts  = full.Split('.');
            JsExpression result = JsExpression.Identifier(parts[0]);

            for (int i = 1; i < parts.Length; i++)
            {
                result = JsExpression.Member(result, parts[i]);
            }
            return(result);
        }
 public void MemberAccessIsNotParenthesizedWhenUsedAsInvocationTarget()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Member(
                           JsExpression.Identifier("x"),
                           "Member"
                           ),
                       new JsExpression[0]
                       ),
                   "x.Member()");
 }
 public void ChainedFunctionCallsAreNotParenthtesized()
 {
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.Invocation(
                           JsExpression.Identifier("x"),
                           new[] { JsExpression.Number(1) }
                           ),
                       new[] { JsExpression.Number(2) }
                       ),
                   "x(1)(2)");
 }
示例#18
0
        private JsType ConvertType(JsClass type)
        {
            if (type.InstanceMethods.Any(m => m.Name == "runTests"))
            {
                _errorReporter.Region = type.CSharpTypeDefinition.Region;
                _errorReporter.Message(MessageSeverity.Error, 7019, string.Format("The type {0} cannot define a method named 'runTests' because it has a [TestFixtureAttribute].", type.CSharpTypeDefinition.FullName));
                return(type);
            }

            var instanceMethods = new List <JsMethod>();
            var tests           = new List <Tuple <string, string, bool, int?, JsFunctionDefinitionExpression> >();

            foreach (var method in type.InstanceMethods)
            {
                var testAttr = _attributeStore.AttributesFor(method.CSharpMember).GetAttribute <TestAttribute>();
                if (testAttr != null)
                {
                    if (!method.CSharpMember.IsPublic || !method.CSharpMember.ReturnType.IsKnownType(KnownTypeCode.Void) || ((IMethod)method.CSharpMember).Parameters.Count > 0 || ((IMethod)method.CSharpMember).TypeParameters.Count > 0)
                    {
                        _errorReporter.Region = method.CSharpMember.Region;
                        _errorReporter.Message(MessageSeverity.Error, 7020, string.Format("Method {0}: Methods decorated with a [TestAttribute] must be public, non-generic, parameterless instance methods that return void.", method.CSharpMember.FullName));
                    }

                    tests.Add(Tuple.Create(testAttr.Description ?? method.CSharpMember.Name, testAttr.Category, testAttr.IsAsync, testAttr.ExpectedAssertionCount >= 0 ? (int?)testAttr.ExpectedAssertionCount : null, method.Definition));
                }
                else
                {
                    instanceMethods.Add(method);
                }
            }

            var testInvocations = new List <JsExpression>();

            foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category))
            {
                if (category.Category != null)
                {
                    testInvocations.Add(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("QUnit"), "module"), JsExpression.String(category.Category)));
                }
                testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) })));
            }

            instanceMethods.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], JsStatement.Block(testInvocations.Select(t => (JsStatement)t)))));

            var result = type.Clone();

            result.InstanceMethods.Clear();
            foreach (var m in instanceMethods)
            {
                result.InstanceMethods.Add(m);
            }
            return(result);
        }
示例#19
0
 public JsExpression ResolveTypeParameter(ITypeParameter tp)
 {
     if (_metadataImporter.GetTypeSemantics(_currentType).IgnoreGenericArguments)
     {
         _errorReporter.Message(Saltarelle.Compiler.Messages._7536, tp.Name, "type", _currentType.FullName);
         return(JsExpression.Null);
     }
     else
     {
         return(JsExpression.Identifier(_namer.GetTypeParameterName(tp)));
     }
 }
        private JsExpression CreateInitInterfaceCall(JsClass type, string ctorName, IList <JsExpression> interfaces)
        {
            var args = new List <JsExpression> {
                JsExpression.Identifier(ctorName), _linker.CurrentAssemblyExpression, CreateInstanceMembers(type, null)
            };

            if (interfaces.Count > 0)
            {
                args.Add(JsExpression.ArrayLiteral(interfaces));
            }
            return(JsExpression.Invocation(JsExpression.Member(_systemScript, InitInterface), args));
        }
示例#21
0
 public static void CreateTemporariesForAllExpressionsThatHaveToBeEvaluatedBeforeNewExpression(IList <JsStatement> statementList, IList <JsExpression> expressions, ExpressionCompileResult newExpressions, Func <string> createTemporaryVariable)
 {
     for (int i = 0; i < expressions.Count; i++)
     {
         if (ExpressionOrderer.DoesOrderMatter(expressions[i], newExpressions))
         {
             var temp = createTemporaryVariable();
             statementList.Add(new JsVariableDeclarationStatement(temp, expressions[i]));
             expressions[i] = JsExpression.Identifier(temp);
         }
     }
 }
 public void NewExpressionIsParenthesizedWhenBeingUsedAsInvocationTarget()
 {
     // Just to get rid of ambiguities
     AssertCorrect(JsExpression.Invocation(
                       JsExpression.New(
                           JsExpression.Identifier("X"),
                           new JsExpression[0]
                           ),
                       new[] { JsExpression.Number(1) }
                       ),
                   "(new X())(1)");
 }
示例#23
0
 public override JsExpression VisitMemberAccessExpression(JsMemberAccessExpression expression, object data)
 {
     if (expression.Target is JsTypeReferenceExpression)
     {
         var type = ((JsTypeReferenceExpression)expression.Target).Type;
         var sem  = _metadataImporter.GetTypeSemantics(type);
         if (string.IsNullOrEmpty(sem.Name) && GetTypeModuleName(type) == null)                      // Handle types marked with [GlobalMethods] that are not from modules.
         {
             return(JsExpression.Identifier(expression.MemberName));
         }
     }
     return(base.VisitMemberAccessExpression(expression, data));
 }
 public void CreatingObjectOfNestedTypeDoesNotCauseUnnecessaryParentheses()
 {
     // Just to get rid of ambiguities
     AssertCorrect(JsExpression.New(
                       JsExpression.Member(
                           JsExpression.Member(
                               JsExpression.Identifier("X"),
                               "Y"
                               ),
                           "Z"
                           )
                       ),
                   "new X.Y.Z()");
 }
        private static JsStatement GenerateBody(string stateVariableName, List <Node> nodes)
        {
            if (nodes.Count == 0)
            {
                return(JsStatement.Break());
            }

            return(JsStatement.Switch(JsExpression.Identifier(stateVariableName),
                                      nodes.Select(n => JsStatement.SwitchSection(n.StateValues.Select(v => JsExpression.Number(v)),
                                                                                  JsStatement.Try(
                                                                                      GenerateBody(stateVariableName, n.Children),
                                                                                      null,
                                                                                      JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier(n.HandlerName), "call"), JsExpression.This))))));
        }
示例#26
0
 public static JsExpression EnsureCanBeEvaluatedMultipleTimes(IList <JsStatement> statementList, JsExpression expression, IList <JsExpression> expressionsThatMustBeEvaluatedBefore, Func <string> createTemporaryVariable)
 {
     if (IsJsExpressionComplexEnoughToGetATemporaryVariable.Analyze(expression))
     {
         CreateTemporariesForAllExpressionsThatHaveToBeEvaluatedBeforeNewExpression(statementList, expressionsThatMustBeEvaluatedBefore, expression, createTemporaryVariable);
         var temp = createTemporaryVariable();
         statementList.Add(new JsVariableDeclarationStatement(temp, expression));
         return(JsExpression.Identifier(temp));
     }
     else
     {
         return(expression);
     }
 }
示例#27
0
        private static JsStatement GenerateBody(string stateVariableName, List <Node> nodes)
        {
            if (nodes.Count == 0)
            {
                return(JsBlockStatement.EmptyStatement);
            }

            return(new JsSwitchStatement(JsExpression.Identifier(stateVariableName),
                                         nodes.Select(n => new JsSwitchSection(n.StateValues.Select(v => JsExpression.Number(v)),
                                                                               new JsTryStatement(
                                                                                   GenerateBody(stateVariableName, n.Children),
                                                                                   null,
                                                                                   new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(JsExpression.Identifier(n.HandlerName), "call"), JsExpression.This)))))));
        }
            private IEnumerable <JsStatement> MakePrefix(Minifier.Function function)
            {
                var result = new List <JsStatement>();

                if (_locals != null)
                {
                    result.Add(JsExpression.Invocation(JsExpression.Identifier("locals"), _locals[function].OrderBy(x => x).Select(JsExpression.Identifier)));
                }
                if (_globals != null)
                {
                    result.Add(JsExpression.Invocation(JsExpression.Identifier("globals"), _globals[function].OrderBy(x => x).Select(JsExpression.Identifier)));
                }
                return(result);
            }
 public void NestedMemberExpressionsAreNotParenthesized()
 {
     AssertCorrect(JsExpression.Member(
                       JsExpression.Member(
                           JsExpression.Member(
                               JsExpression.Identifier("x"),
                               "Member1"
                               ),
                           "Member2"
                           ),
                       "Member3"
                       ),
                   "x.Member1.Member2.Member3");
 }
示例#30
0
            private IEnumerable <JsStatement> MakePrefix(JsDeclarationScope scope)
            {
                var result = new List <JsStatement>();

                if (_locals != null)
                {
                    result.Add(JsExpression.Invocation(JsExpression.Identifier("locals"), _locals[scope].OrderBy(x => x).Select(JsExpression.Identifier)));
                }
                if (_globals != null)
                {
                    result.Add(JsExpression.Invocation(JsExpression.Identifier("globals"), _globals[scope].OrderBy(x => x).Select(JsExpression.Identifier)));
                }
                return(result);
            }