Exemple #1
0
        public JsInvocationExpression MakeGenericType(INamedTypeSymbol unconstructedType, params JsExpression[] typeArguments)
        {
            var containingType = unconstructedType.ContainingType;
            JsExpression target;
            if (containingType != null) 
            {
                target = Type(containingType).Member(unconstructedType.GetShortTypeName()).Invoke().Member(SpecialNames.MakeGenericType);
            }
            else if (!unconstructedType.IsAnonymousType)
            {
                target = Js.Reference(unconstructedType.GetTypeName()).Invoke().Member(SpecialNames.MakeGenericType);
            }
            else 
            {
                target = Js.Reference(unconstructedType.GetTypeName()).Invoke().Member(SpecialNames.MakeGenericType);
            }

            var result = target.Invoke(typeArguments);
            return result;
        }
Exemple #2
0
        public JsBlockStatement CreateTypeFunction(INamedTypeSymbol classType, out JsBlockStatement typeInitializer, out JsBlockStatement staticInitializer)
        {
            var isBuiltIn = classType.IsBuiltIn();
            var extraBuiltInExports = classType.GetExtraBuiltInExports();
            var explicitBaseType = classType.GetAttributeValue<ITypeSymbol>(Context.Instance.JsAttributeType, "BaseType");
            var baseType = 
                explicitBaseType != null ? Type(explicitBaseType) :
                Equals(classType, Context.Instance.ObjectType) ? Js.Reference("Object") : 
                classType.BaseType == null ? Type(Context.Instance.ObjectType) : 
                Js.Reference(classType.BaseType.GetTypeName());
//                classType.BaseType.HasGenericParameters() ? Js.Reference(classType.BaseType.GetTypeName()) :
//                Type(classType.BaseType);

            var block = new JsBlockStatement();
            JsExpression outerClassType = Js.Reference(classType.GetTypeName());

            // Generate type initializer
            typeInitializer = new JsBlockStatement();
//            typeInitializer.Add(StoreInType(SpecialNames.GetAssembly, Js.Reference(classType.ContainingAssembly.GetAssemblyMethodName())));
//            typeInitializer.Add(StoreInPrototype(SpecialNames.TypeField, Js.Reference(SpecialNames.TypeInitializerTypeFunction)));
//            typeInitializer.Add(StoreInType(SpecialNames.BaseType, baseType));
            if (classType.IsExported() && !classType.IsBuiltIn())
            {
//                typeInitializer.Add(StoreInPrototype(SpecialNames.TypeName, Js.Reference(SpecialNames.TypeInitializerTypeFunction).Member(SpecialNames.TypeName)));
            }
            else
            {
                typeInitializer.Add(StoreInPrototype(SpecialNames.TypeName, Js.Primitive(classType.GetFullName())));
                typeInitializer.Add(StoreInType(SpecialNames.TypeName, GetFromPrototype(SpecialNames.TypeName)));
            }
            if (classType.IsBuiltIn())
                typeInitializer.Add(StoreClassGetType());
            typeInitializer.Add(StoreClassCreateType(classType));

            var containingType = classType.ContainingType;
            var typeInitializerFunction = Js.Function(new[] { Js.Parameter(SpecialNames.TypeInitializerTypeFunction), Js.Parameter(SpecialNames.TypeInitializerPrototype) }.Concat(classType.TypeParameters.Select(x => Js.Parameter(x.Name))).Concat(classType.GetAnonymousTypeParameters().Select(x => Js.Parameter(x.Item2))).ToArray()).Body(typeInitializer);

            if (!isBuiltIn)
            {
                var displayName = classType.GetFullName();
                var args = new[]
                {
                    Js.Reference(SpecialNames.Assembly),
                    containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                    Js.Primitive(displayName), 
                    Js.Primitive(classType.HasOrIsEnclosedInGenericParameters()),
                    Js.Array(
                        classType.TypeParameters.Select(x => 
                            (JsExpression)Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Name), 
                                Type(x.BaseType ?? Context.Instance.ObjectType, true)
                            )
                        )
                        .Concat(classType.GetAnonymousTypeParameters().Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Item2),
                                Type(x.Item1 ?? Context.Instance.ObjectType, true)
                            )
                        ))
                        .ToArray()
                    ),
                    baseType,
                    typeInitializerFunction
                };
                if (classType.ContainingType == null && !classType.IsAnonymousType)
                {
                    block.Assign(Js.Reference(classType.ContainingNamespace.GetFullName()).Member(classType.GetShortTypeName()), 
                        Js.Reference(SpecialNames.Define).Invoke(args));
                }
                else if (classType.ContainingType != null)
                {
                    outerClassType = Js.Reference(SpecialNames.TypeInitializerTypeFunction).Member(classType.GetShortTypeName());
                    block.Assign(outerClassType, Js.Reference(SpecialNames.Define).Invoke(args));
                }
                else
                {
                    block.Assign(Js.Reference(classType.GetTypeName()), Js.Reference(SpecialNames.Define).Invoke(args));
                }
            }

            if (classType.IsBuiltIn())
                block.Assign(outerClassType.Member(SpecialNames.TypeInitializer), Js.Reference(SpecialNames.DefineTypeFunction).Invoke(outerClassType, typeInitializerFunction));

            Func<JsExpression, JsExpression> primaryTypeInitializerCall = expression => expression
                .Member("call")
                .Invoke(
                    new[] 
                    { 
                        containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                        outerClassType, 
                        outerClassType.Member("prototype")
                    }
                    .Concat(
                        classType.TypeParameters.Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Name), 
                                Type(x.BaseType ?? Context.Instance.ObjectType, true)
                            )
                        )
                    )
                    .Concat(
                        classType.GetAnonymousTypeParameters().Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Item2),
                                Type(x.Item1 ?? Context.Instance.ObjectType, true)
                            )
                        )
                    )
                    .ToArray()
                );

            if (extraBuiltInExports == null)
            {
                if (!classType.IsBuiltIn())
                    block.Express(outerClassType.Member(SpecialNames.CallTypeInitializer).Invoke());
                else
                    block.Express(primaryTypeInitializerCall(outerClassType.Member(SpecialNames.TypeInitializer)));
            }
            else
            {
                block.Express(primaryTypeInitializerCall(outerClassType.Member(SpecialNames.TypeInitializer)));
                foreach (var extra in extraBuiltInExports)
                {
                    block.Express(outerClassType.Member(SpecialNames.TypeInitializer).Member("call")
                        .Invoke(
                            new[] 
                            { 
                                (JsExpression)Js.Null(), 
                                Js.Reference(extra), 
                                Js.Reference(extra).Member("prototype")
                            }
                            .ToArray()));
                    
                }
            }
            if (classType.IsBuiltIn())
            {
                block.Express(Js.Reference(classType.ContainingAssembly.GetAssemblyTypesArray()).Member("push").Invoke(outerClassType));
            }

            staticInitializer = new JsBlockStatement();
//            staticInitializer.If(GetFromType(SpecialNames.IsStaticInitialized), Js.Return());
//            staticInitializer.Add(StoreInType(SpecialNames.IsStaticInitialized, Js.Primitive(true)));
            if (classType.BaseType != null)
            {
                staticInitializer.Express(Type(classType.BaseType).Member(SpecialNames.StaticInitializer).Invoke());
            }
            var staticInitializerFunction = Js.Function().Body(staticInitializer);
            typeInitializer.Add(StoreInType(SpecialNames.StaticInitializer, Js.Reference(SpecialNames.DefineStaticConstructor).Invoke(Js.Reference(SpecialNames.TypeInitializerTypeFunction), staticInitializerFunction)));

            if (classType.HasOrIsEnclosedInGenericParameters())
            {
                var makeGenericType = new JsBlockStatement();
                var name = containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction);
//                makeGenericType.Return(
//                    Js.Reference(SpecialNames.MakeGenericTypeConstructor)
//                    .Member("call")
//                    .Invoke(name, SpecialTypeOnlyForEnclosingTypes(classType), Js.Reference("arguments"))
//                    .Invoke()
//                );
//                typeInitializer.Add(StoreInType("$", Js.Function().Body(makeGenericType)));
                typeInitializer.Add(StoreInType(SpecialNames.TypeArgs, 
                    Js.Array(classType.TypeArguments.Select(x => Type(x)).ToArray())));
                if (!classType.IsAnonymousType)
                {
                    JsExpression target;
                    if (containingType != null) 
                    {
                        target = Js.This().Member(classType.GetShortTypeName() + SpecialNames.MakeGenericType);
                    }
                    else
                    {
                        target = Js.Reference("window." + classType.GetTypeName() + SpecialNames.MakeGenericType);
                    }

                    typeInitializer.Assign(target, GetFromType("$"));                    
                }
                if (explicitBaseType == null && classType.BaseType != null)
                {
                    typeInitializer.Add(StoreInType(SpecialNames.BaseTypeArgs, 
                        Js.Array(classType.BaseType.TypeArguments.Select(x => x == classType ? Js.Reference(SpecialNames.TypeInitializerTypeFunction) : Type(x)).ToArray())));                
                }
            }

            return block;
        }