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); }
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); }