private JsStatement GenerateResourcesClass(JsClass c)
        {
            var fields = c.StaticInitStatements
                         .OfType <JsExpressionStatement>()
                         .Select(s => s.Expression)
                         .OfType <JsBinaryExpression>()
                         .Where(expr => expr.NodeType == ExpressionNodeType.Assign && expr.Left is JsMemberAccessExpression)
                         .Select(expr => new { Name = ((JsMemberAccessExpression)expr.Left).MemberName, Value = expr.Right });

            return(new JsVariableDeclarationStatement(_namer.GetTypeVariableName(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name), JsExpression.ObjectLiteral(fields.Select(f => new JsObjectLiteralProperty(f.Name, f.Value)))));
        }
            public override JsExpression VisitTypeReferenceExpression(JsTypeReferenceExpression expression, object data)
            {
                var sem = _metadataImporter.GetTypeSemantics(expression.Type);

                if (sem.Type != TypeScriptSemantics.ImplType.NormalType)
                {
                    throw new ArgumentException("The type " + expression.Type.FullName + " appears in the output stage but is not a normal type.");
                }

                if (IsLocalReference(expression.Type))
                {
                    if (string.IsNullOrEmpty(sem.Name))
                    {
                        return(JsExpression.Identifier("exports"));                             // Referencing a [GlobalMethods] type. Since it was not handled in the member expression, we must be in a module, which means that the function should exist on the exports object.
                    }
                    // For types in our own assembly, we can use the $TYPE variable in the pattern "var $TYPE = function() {} ... Type.registerClass(global, 'The.Name', $TYPE)"
                    return(JsExpression.Identifier(_namer.GetTypeVariableName(_metadataImporter.GetTypeSemantics(expression.Type).Name)));
                }

                string moduleName = _metadataImporter.GetModuleName(expression.Type);

                var          parts = sem.Name.Split('.');
                JsExpression result;

                if (moduleName != null)
                {
                    result = JsExpression.Identifier(GetModuleAlias(moduleName));
                    if (!string.IsNullOrEmpty(sem.Name))                        // Test for [GlobalMethods] types.
                    {
                        result = JsExpression.Member(result, parts[0]);
                    }
                }
                else
                {
                    result = JsExpression.Identifier(parts[0]);
                }

                for (int i = 1; i < parts.Length; i++)
                {
                    result = JsExpression.Member(result, parts[i]);
                }
                return(result);
            }
        public IList <JsStatement> Rewrite(IEnumerable <JsType> types, ICompilation compilation)
        {
            var netSystemType = compilation.FindType(KnownTypeCode.Type).GetDefinition();
            var systemType    = new JsTypeReferenceExpression(netSystemType.ParentAssembly, _metadataImporter.GetTypeSemantics(netSystemType).Name);

            var result = new List <JsStatement>();

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

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

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

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

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

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

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

            return(result);
        }
Пример #4
0
 public JsExpression GetScriptType(IType type, TypeContext context)
 {
     if (type.TypeParameterCount > 0 && !(type is ParameterizedType) && context == TypeContext.TypeOf)
     {
         // This handles open generic types ( typeof(C<,>) )
         return(_createTypeReferenceExpression(type.GetDefinition().ToTypeReference()));
     }
     else if (type.Kind == TypeKind.Enum && (context == TypeContext.CastTarget || context == TypeContext.InvokeConstructor))
     {
         var def = type.GetDefinition();
         return(_createTypeReferenceExpression(def.EnumUnderlyingType.ToTypeReference()));
     }
     else if (type.Kind == TypeKind.Array)
     {
         return(_createTypeReferenceExpression(KnownTypeReference.Array));
     }
     else if (type.Kind == TypeKind.Delegate)
     {
         return(_createTypeReferenceExpression(KnownTypeReference.Delegate));
     }
     else if (type is ITypeParameter)
     {
         return(JsExpression.Identifier(_getTypeParameterName((ITypeParameter)type)));
     }
     else if (type is ParameterizedType)
     {
         var pt  = (ParameterizedType)type;
         var def = pt.GetDefinition();
         var sem = _metadataImporter.GetTypeSemantics(def);
         if (sem.Type == TypeScriptSemantics.ImplType.NormalType && !sem.IgnoreGenericArguments)
         {
             return(JsExpression.Invocation(JsExpression.MemberAccess(_createTypeReferenceExpression(KnownTypeReference.Type), "makeGenericType"), _createTypeReferenceExpression(type.GetDefinition().ToTypeReference()), JsExpression.ArrayLiteral(pt.TypeArguments.Select(a => GetScriptType(a, TypeContext.GenericArgument)))));
         }
         else
         {
             return(GetScriptType(def, context));
         }
     }
     else if (type is ITypeDefinition)
     {
         var td = (ITypeDefinition)type;
         if (_metadataImporter.IsSerializable(td) && (context == TypeContext.CastTarget || context == TypeContext.Inheritance))
         {
             return(null);
         }
         else if (!_metadataImporter.IsRealType(td))
         {
             if (context == TypeContext.CastTarget || context == TypeContext.Inheritance)
             {
                 return(null);
             }
             else
             {
                 return(_createTypeReferenceExpression(KnownTypeReference.Object));
             }
         }
         else
         {
             var sem   = _metadataImporter.GetTypeSemantics(td);
             var jsref = _createTypeReferenceExpression(td.ToTypeReference());
             if (td.TypeParameterCount > 0 && !sem.IgnoreGenericArguments)
             {
                 // This handles the case of resolving the current type, eg. to access a static member.
                 return(JsExpression.Invocation(JsExpression.MemberAccess(_createTypeReferenceExpression(KnownTypeReference.Type), "makeGenericType"), _createTypeReferenceExpression(type.GetDefinition().ToTypeReference()), JsExpression.ArrayLiteral(td.TypeParameters.Select(a => GetScriptType(a, TypeContext.GenericArgument)))));
             }
             else
             {
                 return(jsref);
             }
         }
     }
     else if (type.Kind == TypeKind.Anonymous && context == TypeContext.GenericArgument)
     {
         return(_createTypeReferenceExpression(KnownTypeReference.Object));
     }
     else if (type.Kind == TypeKind.Null || type.Kind == TypeKind.Dynamic)
     {
         return(_createTypeReferenceExpression(KnownTypeReference.Object));
     }
     else
     {
         throw new InvalidOperationException("Could not determine the script type for " + type.ToString() + ", context " + context);
     }
 }