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;}"); }
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); }
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")), } }); }
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")); } }
public JsExpression ResolveTypeParameter(ITypeParameter tp) { if (_isGenericSpecialization && tp.OwnerType == EntityType.TypeDefinition) { return(JsExpression.Identifier(_namer.GetTypeParameterName(tp))); } else { return(_systemObject); } }
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)"); }
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); }
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)); }
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)"); }
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)))))); }
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); } }
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"); }
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); }