public JsCatchClause(string identifier, JsStatement body) { if (identifier == null) throw new ArgumentNullException("identifier"); if (body == null) throw new ArgumentNullException("body"); Identifier = identifier; Body = JsBlockStatement.MakeBlock(body); }
public JsSwitchSection(IEnumerable<JsExpression> values, JsStatement body) { if (values == null) throw new ArgumentNullException("values"); if (body == null) throw new ArgumentNullException("body"); Values = values.AsReadOnly(); if (Values.Count == 0) throw new ArgumentException("Values cannot be empty", "values"); Body = JsStatement.EnsureBlock(body); }
public void Add(JsStatement statement) { if (Substates.Any()) throw new Exception("Cannot add a statement to a state that contains substates"); InternalAdd(statement); }
private bool IsNextStatementReachable(JsStatement current) { while (current is JsBlockStatement) { var block = (JsBlockStatement)current; if (block.Statements.Count == 0) return true; current = block.Statements[block.Statements.Count - 1]; } var ifst = current as JsIfStatement; if (ifst != null) { return ifst.Else == null || ifst.Then.Statements.Count == 0 || ifst.Else.Statements.Count == 0 || IsNextStatementReachable(ifst.Then.Statements[ifst.Then.Statements.Count - 1]) || IsNextStatementReachable(ifst.Else.Statements[ifst.Else.Statements.Count - 1]); } return !(current is JsReturnStatement || current is JsGotoStatement || current is JsGotoStateStatement || current is JsThrowStatement || current is JsBreakStatement || current is JsContinueStatement); }
public void CanAnalyzeStatements() { var asm = Common.CreateMockAssembly(); var t1 = Common.CreateMockTypeDefinition("Type", asm); var t2 = Common.CreateMockTypeDefinition("Type", asm); var t3 = Common.CreateMockTypeDefinition("Type", asm); var ast = new JsStatement[] { new JsIfStatement(JsExpression.Member(new JsTypeReferenceExpression(t1), "X"), new JsBlockStatement( new JsExpressionStatement(JsExpression.Add(new JsTypeReferenceExpression(t2), new JsTypeReferenceExpression(t3))) ), null), new JsExpressionStatement(JsExpression.Add(JsExpression.Number(1), new JsTypeReferenceExpression(t1))), }; var refs = TypeReferenceFinder.Analyze(ast); Assert.That(refs, Has.Count.EqualTo(3)); Assert.That(refs.Contains(t1)); Assert.That(refs.Contains(t2)); Assert.That(refs.Contains(t3)); }
public bool TryUnwrapJsniStatement(ExpressionStatementSyntax statement, out JsStatement result) { var expression = statement.Expression; if (expression is InvocationExpressionSyntax) { var jsniInvocation = (InvocationExpressionSyntax)expression; var symbolInfo = Context.Instance.Compilation.GetSemanticModel(expression.SyntaxTree).GetSymbolInfo(jsniInvocation); var method = (IMethodSymbol)symbolInfo.Symbol; var arguments = jsniInvocation.ArgumentList.Arguments.Select(x => (JsExpression)x.Accept(transformer)).ToArray(); if (symbolInfo.Symbol == null) { var classText = statement.FirstAncestorOrSelf<ClassDeclarationSyntax>().NormalizeWhitespace().ToString(); var diagnostics = transformer.model.GetDiagnostics().Select(x => x.ToString()).ToArray(); } if (method.ReducedFrom != null && !method.ReducedFrom.Equals(method)) { method = method.ReducedFrom; var target = (JsExpression)jsniInvocation.Expression.Accept(transformer); var methodTarget = target is JsMemberReferenceExpression ? ((JsMemberReferenceExpression)target).Target : target; arguments = new[] { methodTarget }.Concat(arguments).ToArray(); } if (method != null && Equals(method.ContainingType, Context.Instance.JsniType)) { switch (method.Name) { case "forin": var target = arguments[0]; var invocation = (JsInvocationExpression)arguments[1]; var function = (JsFunction)invocation.Arguments[1]; result = Js.ForIn(function.Parameters[0].Name, target).Body(function.Body); return true; } } } result = null; return false; }
public static IList <JsStatement> Process(IMetadataImporter metadataImporter, INamer namer, ICompilation compilation, IList <JsStatement> statements) { var usedSymbols = UsedSymbolsGatherer.Analyze(statements); var importer = new ImportVisitor(metadataImporter, namer, compilation.MainAssembly, usedSymbols); var body = statements.Select(s => importer.VisitStatement(s, null)).ToList(); var moduleDependencies = importer._moduleAliases.Concat(MetadataUtils.GetAdditionalDependencies(compilation.MainAssembly)); if (MetadataUtils.IsAsyncModule(compilation.MainAssembly)) { body.InsertRange(0, new[] { JsStatement.UseStrict, JsStatement.Var("exports", JsExpression.ObjectLiteral()) }); body.Add(JsStatement.Return(JsExpression.Identifier("exports"))); var pairs = new[] { new KeyValuePair <string, string>("mscorlib", namer.GetVariableName("_", usedSymbols)) } .Concat(moduleDependencies.OrderBy(x => x.Key)) .ToList(); body = new List <JsStatement> { JsExpression.Invocation( JsExpression.Identifier("define"), JsExpression.ArrayLiteral(pairs.Select(p => JsExpression.String(p.Key))), JsExpression.FunctionDefinition( pairs.Select(p => p.Value), JsStatement.Block(body) ) ) }; } else if (moduleDependencies.Any()) { // If we require any module, we require mscorlib. This should work even if we are a leaf module that doesn't include any other module because our parent script will do the mscorlib require for us. body.InsertRange(0, new[] { JsStatement.UseStrict, JsExpression.Invocation(JsExpression.Identifier("require"), JsExpression.String("mscorlib")) } .Concat(moduleDependencies .OrderBy(x => x.Key).OrderBy(x => x.Key) .Select(x => JsStatement.Var( x.Value, JsExpression.Invocation( JsExpression.Identifier("require"), JsExpression.String(x.Key)))) .ToList())); } else { body.Insert(0, JsStatement.UseStrict); body = new List <JsStatement> { JsExpression.Invocation(JsExpression.FunctionDefinition(new string[0], JsStatement.Block(body))) }; } return(body); }
public void ContinueStatementIsCorrectlyOutput() { AssertCorrect(JsStatement.Continue(), "continue;"); AssertCorrect(JsStatement.Continue("someLabel"), "continue someLabel;"); }
public static JsFunctionDefinitionExpression FunctionDefinition(IEnumerable <string> parameterNames, JsStatement body, string name = null) { return(new JsFunctionDefinitionExpression(parameterNames, body, name)); }
public void BlockStatementsAreCorrectlyOutput() { AssertCorrect(JsStatement.Block(new JsStatement[0]), "{}"); AssertCorrect(JsStatement.Block(new JsStatement[] { JsExpression.Identifier("X") }), "{X;}"); AssertCorrect(JsStatement.Block(new JsStatement[] { JsExpression.Identifier("X"), JsExpression.Identifier("Y") }), "{X;Y;}"); }
public void ForStatementsAreCorrectlyOutput() { AssertCorrect(JsStatement.For(JsStatement.Var("i", JsExpression.Number(0)), JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)), JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")), JsStatement.EmptyBlock), "for(var i=0;i<10;i++){}"); AssertCorrect(JsStatement.For(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0)), JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)), JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")), JsStatement.EmptyBlock), "for(i=0;i<10;i++){}"); AssertCorrect(JsStatement.For(JsStatement.Var(JsStatement.Declaration("i", JsExpression.Number(0)), JsStatement.Declaration("j", JsExpression.Number(1))), JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)), JsExpression.Comma(JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")), JsExpression.PostfixPlusPlus(JsExpression.Identifier("j"))), JsStatement.EmptyBlock), "for(var i=0,j=1;i<10;i++,j++){}"); AssertCorrect(JsStatement.For(JsStatement.Empty, null, null, JsStatement.EmptyBlock), "for(;;){}"); }
private static JsExpression ConstructConstructorInfo(IMethod constructor, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType) { var properties = GetCommonMemberInfoProperties(constructor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); var sem = metadataImporter.GetConstructorSemantics(constructor); if (sem.Type == ConstructorScriptSemantics.ImplType.NotUsableFromScript) { errorReporter.Message(Messages._7200, constructor.FullName); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Constructor))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(constructor.Parameters.Select(p => instantiateType(p.Type))))); if (sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) { properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } if (sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } if ((sem.Type == ConstructorScriptSemantics.ImplType.UnnamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) && sem.ExpandParams) { properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); } if (sem.Type == ConstructorScriptSemantics.ImplType.Json || sem.Type == ConstructorScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet <string>(); var parameters = new List <IVariable>(); var variables = new Dictionary <IVariable, VariableData>(); IList <ResolveResult> constructorParameters = null; IList <ResolveResult> initializerStatements = null; if (sem.Type == ConstructorScriptSemantics.ImplType.Json && constructor.DeclaringType.Kind == TypeKind.Anonymous) { initializerStatements = new List <ResolveResult>(); foreach (var p in constructor.DeclaringType.GetProperties()) { string paramName = MakeCamelCase(p.Name); string name = namer.GetVariableName(paramName, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.ReturnType, paramName, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); initializerStatements.Add(new OperatorResolveResult(p.ReturnType, ExpressionType.Assign, new MemberResolveResult(new InitializedObjectResolveResult(constructor.DeclaringType), p), new LocalResolveResult(variable))); } } else { constructorParameters = new List <ResolveResult>(); foreach (var p in constructor.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); constructorParameters.Add(new LocalResolveResult(variable)); } } var compileResult = CompileConstructorInvocation(constructor, initializerStatements, constructor.DeclaringTypeDefinition, constructor, constructorParameters, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); properties.Add(new JsObjectLiteralProperty("def", definition)); } return(JsExpression.ObjectLiteral(properties)); }
private void AssertCorrect(JsStatement stmt, string expected) { var actual = OutputFormatter.FormatMinified(stmt); Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n"))); }
public bool Compile(CompilerOptions options) { string intermediateAssemblyFile = Path.GetTempFileName(), intermediateDocFile = Path.GetTempFileName(); var actualOut = Console.Out; var er = new ErrorReporterWrapper(_errorReporter, actualOut); try { Console.SetOut(new StringWriter()); // I don't trust the third-party libs to not generate spurious random messages, so make sure that any of those messages are suppressed. var settings = MapSettings(options, intermediateAssemblyFile, intermediateDocFile, er); if (er.HasErrors) { return(false); } if (!options.AlreadyCompiled) { // Compile the assembly var ctx = new CompilerContext(settings, new ConvertingReportPrinter(er)); var d = new Mono.CSharp.Driver(ctx); d.Compile(); if (er.HasErrors) { return(false); } } var references = LoadReferences(settings.AssemblyReferences, er); if (references == null) { return(false); } PreparedCompilation compilation = PreparedCompilation.CreateCompilation(settings.AssemblyName, options.SourceFiles.Select(f => new SimpleSourceFile(f, settings.Encoding)), references.Select(r => r.Item1), options.DefineConstants, LoadResources(options.EmbeddedResources)); IMethod entryPoint = FindEntryPoint(options, er, compilation); var container = new WindsorContainer(); foreach (var plugin in TopologicalSortPlugins(references).Reverse()) { RegisterPlugin(container, plugin); } var attributeStore = new AttributeStore(compilation.Compilation, er); container.Register(Component.For <IErrorReporter>().Instance(er), Component.For <CompilerOptions>().Instance(options), Component.For <IAttributeStore>().Instance(attributeStore), Component.For <ICompilation>().Instance(compilation.Compilation), Component.For <ICompiler>().ImplementedBy <Compiler.Compiler>() ); InitializeAttributeStore(attributeStore, container, compilation.Compilation); container.Resolve <IMetadataImporter>().Prepare(compilation.Compilation.GetAllTypeDefinitions()); var compiledTypes = container.Resolve <ICompiler>().Compile(compilation); foreach (var rewriter in container.ResolveAll <IJSTypeSystemRewriter>()) { compiledTypes = rewriter.Rewrite(compiledTypes); } var invoker = new OOPEmulatorInvoker(container.Resolve <IOOPEmulator>(), container.Resolve <IMetadataImporter>(), container.Resolve <IErrorReporter>()); var js = invoker.Process(compiledTypes.ToList(), entryPoint); js = container.Resolve <ILinker>().Process(js); if (er.HasErrors) { return(false); } string outputAssemblyPath = !string.IsNullOrEmpty(options.OutputAssemblyPath) ? options.OutputAssemblyPath : Path.ChangeExtension(options.SourceFiles[0], ".dll"); string outputScriptPath = !string.IsNullOrEmpty(options.OutputScriptPath) ? options.OutputScriptPath : Path.ChangeExtension(options.SourceFiles[0], ".js"); if (!options.AlreadyCompiled) { try { File.Copy(intermediateAssemblyFile, outputAssemblyPath, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7950, ex.Message); return(false); } if (!string.IsNullOrEmpty(options.DocumentationFile)) { try { File.Copy(intermediateDocFile, options.DocumentationFile, true); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7952, ex.Message); return(false); } } } if (options.MinimizeScript) { js = ((JsBlockStatement)Minifier.Process(JsStatement.Block(js))).Statements; } string script = options.MinimizeScript ? OutputFormatter.FormatMinified(js) : OutputFormatter.Format(js); try { File.WriteAllText(outputScriptPath, script, settings.Encoding); } catch (IOException ex) { er.Region = DomRegion.Empty; er.Message(Messages._7951, ex.Message); return(false); } return(true); } catch (Exception ex) { er.Region = DomRegion.Empty; er.InternalError(ex.ToString()); return(false); } finally { if (!options.AlreadyCompiled) { try { File.Delete(intermediateAssemblyFile); } catch {} try { File.Delete(intermediateDocFile); } catch {} } if (actualOut != null) { Console.SetOut(actualOut); } } }
public static JsExpression ConstructAttribute(IAttribute attr, ITypeDefinition currentType, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter) { errorReporter.Region = attr.Region; var initializerStatements = attr.NamedArguments.Select(a => new OperatorResolveResult(a.Key.ReturnType, ExpressionType.Assign, new MemberResolveResult(new InitializedObjectResolveResult(attr.AttributeType), a.Key), a.Value)).ToList <ResolveResult>(); var constructorResult = CompileConstructorInvocation(attr.Constructor, initializerStatements, currentType, null, attr.PositionalArguments, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, null, null); if (constructorResult.AdditionalStatements.Count > 0) { return(JsExpression.Invocation(JsExpression.FunctionDefinition(new string[0], JsStatement.Block(constructorResult.AdditionalStatements.Concat(new[] { JsStatement.Return(constructorResult.Expression) }))))); } else { return(constructorResult.Expression); } }
public override async Task <bool> WriteStatementAsync(ScriptScopeContext scope, JsStatement statement, CancellationToken token) { var page = scope.PageResult; if (statement is JsExpressionStatement exprStatement) { var value = exprStatement.Expression.Evaluate(scope); if (value != null && !ReferenceEquals(value, JsNull.Value) && value != StopExecution.Value && value != IgnoreResult.Value) { var strValue = page.Format.EncodeValue(value); if (!string.IsNullOrEmpty(strValue)) { var bytes = strValue.ToUtf8Bytes(); await scope.OutputStream.WriteAsync(bytes, token).ConfigAwait(); } await scope.OutputStream.WriteAsync(JsTokenUtils.NewLineUtf8, token).ConfigAwait(); } } else if (statement is JsFilterExpressionStatement filterStatement) { await page.WritePageFragmentAsync(scope, filterStatement.FilterExpression, token).ConfigAwait(); if (!page.Context.RemoveNewLineAfterFiltersNamed.Contains(filterStatement.FilterExpression.LastFilterName)) { await scope.OutputStream.WriteAsync(JsTokenUtils.NewLineUtf8, token).ConfigAwait(); } } else if (statement is JsBlockStatement blockStatement) { await page.WriteStatementsAsync(scope, blockStatement.Statements, token).ConfigAwait(); } else if (statement is JsPageBlockFragmentStatement pageFragmentStatement) { await page.WritePageFragmentAsync(scope, pageFragmentStatement.Block, token).ConfigAwait(); } else { return(false); } return(true); }
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)); }
private void AddClassMembers(JsClass c, string typevarName, List <JsStatement> stmts) { if (c.NamedConstructors.Count > 0) { stmts.AddRange(c.NamedConstructors.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), m.Definition))); } var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic); bool hasCreateInstance = false; if (defaultConstructor != null) { var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor); if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript) { var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance"), JsExpression.FunctionDefinition(new string[0], JsStatement.Block(createInstance.AdditionalStatements.Concat(new[] { JsStatement.Return(createInstance.Expression) }))))); hasCreateInstance = true; } } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "getDefaultValue"), hasCreateInstance ? JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance") : JsExpression.FunctionDefinition(EmptyList <string> .Instance, JsStatement.Return(JsExpression.New(JsExpression.Identifier(typevarName)))))); if (_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Type == TypeScriptSemantics.ImplType.MutableValueType) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "$clone"), GenerateStructCloneMethod(c.CSharpTypeDefinition, typevarName, hasCreateInstance))); } } stmts.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), RewriteMethod(m)))); if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition, _attributeStore)) { string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition, _attributeStore); if (!string.IsNullOrEmpty(typeCheckCode)) { var oldReg = _errorReporter.Region; _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region; var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation); var errors = new List <string>(); var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add); if (errors.Count == 0) { var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer); var result = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0], n => { var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); if (type.Kind == TypeKind.Unknown) { errors.Add("Unknown type '" + n + "' specified in inline implementation"); return(JsExpression.Null); } return(_runtimeLibrary.InstantiateType(type, context)); }, t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), errors.Add); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"), JsExpression.FunctionDefinition(new[] { "obj" }, JsStatement.Return(result)))); foreach (var e in errors) { _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e); } } _errorReporter.Region = oldReg; } } if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var args = new List <JsExpression> { JsExpression.Identifier(typevarName), new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp)))), CreateInstanceMembers(c, typevarName), }; if (c.CSharpTypeDefinition.Kind != TypeKind.Interface) { args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null))); } args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition))))); stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterfaceInstance : RegisterGenericClassInstance), args)); if (c.CSharpTypeDefinition.Kind == TypeKind.Class && c.NamedConstructors.Count > 0) { stmts.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(typevarName))); } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "__class"), JsExpression.False)); } var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true); if (metadata != null) { stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(typevarName), metadata)); } } }
private JsExpression RewriteMethod(JsMethod method) { return(method.TypeParameterNames.Count == 0 ? method.Definition : JsExpression.FunctionDefinition(method.TypeParameterNames, JsStatement.Return(method.Definition))); }
private static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType, MethodScriptSemantics semanticsIfAccessor) { if (m is IMethod && ((IMethod)m).IsConstructor) { return(ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)); } var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType); if (m.IsStatic) { properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True)); } if (m is IMethod) { var method = (IMethod)m; var sem = semanticsIfAccessor ?? metadataImporter.GetMethodSemantics(method); if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7201, m.FullName, "method"); return(JsExpression.Null); } if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams) { properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method))); if (sem.Type == MethodScriptSemantics.ImplType.InlineCode) { var usedNames = new HashSet <string>(); var parameters = new List <IVariable>(); var variables = new Dictionary <IVariable, VariableData>(); var arguments = new List <ResolveResult>(); foreach (var p in method.Parameters) { string name = namer.GetVariableName(p.Name, usedNames); usedNames.Add(name); var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty); parameters.Add(variable); variables.Add(variable, new VariableData(name, null, false)); arguments.Add(new LocalResolveResult(variable)); } var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {}); var compileResult = Compile(CreateMethodInvocationResolveResult(method, method.IsStatic ? (ResolveResult) new TypeResolveResult(method.DeclaringType) : new ThisResolveResult(method.DeclaringType), arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames); var definition = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), JsStatement.Block(compileResult.AdditionalStatements.Concat(new[] { JsStatement.Return(compileResult.Expression) }))); if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == SymbolKind.Method)) { definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), JsStatement.Return(definition)); properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } properties.Add(new JsObjectLiteralProperty("def", definition)); } else { if (IsJsGeneric(method, metadataImporter)) { properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count))); } if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) { properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True)); } properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType))); properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type))))); } else if (m is IField) { var field = (IField)m; var sem = metadataImporter.GetFieldSemantics(field); if (sem.Type != FieldScriptSemantics.ImplType.Field) { errorReporter.Message(Messages._7201, m.FullName, "field"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType))); properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name))); } else if (m is IProperty) { var prop = (IProperty)m; var sem = metadataImporter.GetPropertySemantics(prop); properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property))); properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType))); if (prop.Parameters.Count > 0) { properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type))))); } switch (sem.Type) { case PropertyScriptSemantics.ImplType.GetAndSetMethods: if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "getter"); return(JsExpression.Null); } if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "property", "setter"); return(JsExpression.Null); } if (sem.GetMethod != null) { properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.GetMethod))); } if (sem.SetMethod != null) { properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.SetMethod))); } break; case PropertyScriptSemantics.ImplType.Field: if (prop.CanGet) { properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType))); } if (prop.CanSet) { properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType))); } properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName))); break; default: errorReporter.Message(Messages._7201, m.FullName, "property"); return(JsExpression.Null); } } else if (m is IEvent) { var evt = (IEvent)m; var sem = metadataImporter.GetEventSemantics(evt); if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods) { errorReporter.Message(Messages._7201, m.FullName, "event"); return(JsExpression.Null); } if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor"); return(JsExpression.Null); } if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode) { errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor"); return(JsExpression.Null); } properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event))); properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.AddMethod))); properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType, sem.RemoveMethod))); } else { throw new ArgumentException("Invalid member " + m); } return(JsExpression.ObjectLiteral(properties)); }
public static JsLabeledStatement Label(string label, JsStatement statement) { return(new JsLabeledStatement(label, statement)); }
public static JsFunction Body(this JsFunction function, JsStatement statement) { function.Body.Aggregate(statement); return(function); }
public void CommentsAreIgnored() { AssertCorrect(JsStatement.Comment("Line 1"), ""); }
public static JsIfStatement If(JsExpression condition, JsStatement ifTrue, JsStatement ifFalse = null) { return(new JsIfStatement(condition, ifTrue, ifFalse)); }
public void VariableDeclarationStatementsAreCorrectlyOutput() { AssertCorrect(JsStatement.Var(new[] { JsStatement.Declaration("i", null) }), "var i;"); AssertCorrect(JsStatement.Var(new[] { JsStatement.Declaration("i", null), JsStatement.Declaration("j", null) }), "var i,j;"); AssertCorrect(JsStatement.Var(new[] { JsStatement.Declaration("i", JsExpression.Number(0)) }), "var i=0;"); AssertCorrect(JsStatement.Var(new[] { JsStatement.Declaration("i", JsExpression.Number(0)), JsStatement.Declaration("j", JsExpression.Number(1)) }), "var i=0,j=1;"); AssertCorrect(JsStatement.Var(new[] { JsStatement.Declaration("i", JsExpression.Number(0)), JsStatement.Declaration("j", null) }), "var i=0,j;"); }
public static JsForInStatement Body(this JsForInStatement forInStatement, JsStatement statement) { forInStatement.Body = statement; return(forInStatement); }
public void BreakStatementIsCorrectlyOutput() { AssertCorrect(JsStatement.Break(), "break;"); AssertCorrect(JsStatement.Break("someLabel"), "break someLabel;"); }
public static JsForStatement Body(this JsForStatement forStatement, JsStatement body) { forStatement.Body = body; return(forStatement); }
public void WhileStatementIsCorrectlyOutput() { AssertCorrect(JsStatement.While(JsExpression.True, JsStatement.Block(JsStatement.Var("x", JsExpression.Number(0)))), "while(true){var x=0;}"); }
internal void InternalAdd(JsStatement statement) { ((List<JsStatement>)Statements).Add(statement); }
public JsLabeledStatement(string label, JsStatement statement) { Label = label; Statement = statement; }
private void AssertCorrect(JsStatement stmt, string expected) { var actual = OutputFormatter.Format(stmt); Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n"))); }
private JsBlockStatement ProcessAsyncMethod(JsBlockStatement statement, string stateMachineMethodName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func<JsExpression, JsExpression> makeSetResult, Func<JsExpression, JsExpression> makeSetException, Func<JsExpression> getTask, Func<JsExpression, JsExpression, JsExpression> bindToContext) { _stateMachineMethodName = stateMachineMethodName; _doFinallyBlocksVariableName = doFinallyBlocksVariableName; _makeSetResult = taskCompletionSource != null ? makeSetResult : null; _needDoFinallyBlocksVariable = new HasAwaitInsideTryWithFinallyVisitor().Analyze(statement); var result = Process(statement, isIteratorBlock: false, isAsync: true); var hoistResult = VariableHoistingVisitor.Process(result); string catchVariable = _allocateTempVariable(); JsStatement body; if (taskCompletionSource != null && (statement.Statements.Count == 0 || IsNextStatementReachable(statement.Statements[statement.Statements.Count - 1]))) { // If we return the task, and if we risk falling out of the original method, we need to add a setResult call. body = JsStatement.Block(hoistResult.Item1.Statements.Concat(new JsStatement[] { makeSetResult(null) })); } else { body = hoistResult.Item1; } if (taskCompletionSource != null) body = JsStatement.Try(body, JsStatement.Catch(catchVariable, JsStatement.Block(makeSetException(JsExpression.Identifier(catchVariable)))), null); IEnumerable<JsVariableDeclaration> declarations = new[] { JsStatement.Declaration(_stateVariableName, JsExpression.Number(0)) }; if (taskCompletionSource != null) declarations = declarations.Concat(new[] { taskCompletionSource }); declarations = declarations.Concat(hoistResult.Item2.Select(v => JsStatement.Declaration(v, null))); if (_needDoFinallyBlocksVariable) body = JsStatement.Block(new[] { JsStatement.Var(_doFinallyBlocksVariableName, JsExpression.True) }.Concat(body is JsBlockStatement ? ((JsBlockStatement)body).Statements : (IEnumerable<JsStatement>)new[] { body })); var stateMachine = JsExpression.FunctionDefinition(new string[0], body); var boundStateMachine = UsesThisVisitor.Analyze(stateMachine.Body) ? bindToContext(stateMachine, JsExpression.This) : stateMachine; IEnumerable<JsStatement> stmts = new JsStatement[] { JsStatement.Var(declarations), JsStatement.Var(stateMachineMethodName, boundStateMachine), JsExpression.Invocation(JsExpression.Identifier(stateMachineMethodName)) }; if (taskCompletionSource != null) stmts = stmts.Concat(new[] { JsStatement.Return(getTask()) }); return JsStatement.Block(stmts); }
public object VisitStatement(JsStatement statement, bool addNewline) { return(statement.Accept(this, addNewline)); }
public static JsSwitchSection Statement(this JsSwitchSection section, JsStatement statement) { section.Statements.Add(statement); return(section); }
public JsStatement Process(JsStatement stmt) { return(VisitStatement(stmt, null)); }
protected void AssertCorrect(JsStatement stmt, string expected) { var actual = OutputFormatter.Format(stmt, allowIntermediates: true); Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n"))); }
public static JsDoWhileStatement DoWhile(JsExpression condition, JsStatement statement) { return(new JsDoWhileStatement(condition, statement)); }
public static void If(this JsBlockStatement blockStatement, JsExpression condition, JsStatement ifTrue, JsStatement ifFalse = null) { blockStatement.Add(If(condition, ifTrue, ifFalse)); }
public void Add(JsStatement statement) { statements.Add(statement); }