Ejemplo n.º 1
0
        public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node)
        {
            var jsBlock = new JsBlockStatement();

            var model = Context.Instance.Compilation.GetSemanticModel(node.SyntaxTree);
            var classType = (INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(model, node);
            if (processedTypes.Contains(classType))
                return;
            processedTypes.Add(classType);

            JsBlockStatement typeInitializer;
            JsBlockStatement staticInitializer;
            jsBlock.Aggregate(idioms.CreateTypeFunction(classType, out typeInitializer, out staticInitializer));
            
            // Create default constructor
            var constructorBlock = new JsBlockStatement();
            constructorBlock.Express(idioms.InvokeMethodAsThis(classType.BaseType.InstanceConstructors.Single(x => x.Parameters.Count() == 0)));
            var constructor = classType.InstanceConstructors.Single();

            typeInitializer.Add(idioms.StoreInPrototype(constructor.GetMemberName(), Js.Reference(SpecialNames.DefineConstructor).Invoke(
                Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                Js.Function().Body(constructorBlock))));
            
            foreach (var property in classType.GetMembers().OfType<IPropertySymbol>())
            {
                typeInitializer.Aggregate(CreateProperty(property));
            }

            Action action = () =>
            {
                body.Aggregate(jsBlock);
            };
            actions.Add(Tuple.Create(classType, action));
        }
Ejemplo n.º 2
0
        private void ProcessNamespace(string ns)
        {
            if (processedNamespaces.Contains(ns))
            {
                return;
            }
            processedNamespaces.Add(ns);

            var lastDotIndex    = ns.LastIndexOf('.');
            var parentNamespace = lastDotIndex != -1 ? ns.Substring(0, lastDotIndex) : null;

            if (parentNamespace != null)
            {
                ProcessNamespace(parentNamespace);
            }

            JsBinaryExpression result;

            if (lastDotIndex == -1)
            {
                result = Js.Assign(Js.Reference("window").Member(ns), Js.Object());
            }
            else
            {
                result = Js.Assign(Js.Reference(ns), Js.Object());
            }
            result.Right = Js.Binary(JsBinaryOperator.LogicalOr, result.Left, result.Right);
            body.Express(result);
        }
Ejemplo n.º 3
0
        public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node)
        {
            var jsBlock = new JsBlockStatement();

            var model     = Context.Instance.Compilation.GetSemanticModel(node.SyntaxTree);
            var classType = (INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(model, node);

            if (processedTypes.Contains(classType))
            {
                return;
            }
            processedTypes.Add(classType);

            JsBlockStatement typeInitializer;
            JsBlockStatement staticInitializer;

            jsBlock.Aggregate(idioms.CreateTypeFunction(classType, out typeInitializer, out staticInitializer));

            // Create default constructor
            var constructorBlock = new JsBlockStatement();

            constructorBlock.Express(idioms.InvokeMethodAsThis(classType.BaseType.InstanceConstructors.Single(x => x.Parameters.Count() == 0)));
            var constructor = classType.InstanceConstructors.Single();

            typeInitializer.Add(idioms.StoreInPrototype(constructor.GetMemberName(), Js.Reference(SpecialNames.DefineConstructor).Invoke(
                                                            Js.Reference(SpecialNames.TypeInitializerTypeFunction),
                                                            Js.Function().Body(constructorBlock))));

            foreach (var property in classType.GetMembers().OfType <IPropertySymbol>())
            {
                typeInitializer.Aggregate(CreateProperty(property));
            }

            Action action = () =>
            {
                body.Aggregate(jsBlock);
            };

            actions.Add(Tuple.Create(classType, action));
        }
Ejemplo n.º 4
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;
        }
Ejemplo n.º 5
0
        private JsExpression CreateAttributes(ISymbol symbol)
        {
            var result = Js.Array();
            foreach (var attribute in symbol.GetAttributes().Where(x => x.AttributeClass.IsExported()))
            {
                if (!attribute.AttributeClass.IsExported())
                    continue;

                var attributeInstance = CreateObject(attribute.AttributeConstructor,
                    attribute.ConstructorArguments.Select(x => GetConstantValue(x.Type, x.Value)).ToArray());
                if (attribute.NamedArguments.Any())
                {
                    // Wrap initialization in an anonymous function
                    var initializerBlock = new JsBlockStatement();
                    var variable = Js.Variable("$obj$", attributeInstance);
                    initializerBlock.Local(variable);

                    // Process named arguments
                    foreach (var argument in attribute.NamedArguments)
                    {
                        initializerBlock.Express(variable.GetReference().Member("set_" + argument.Key).Invoke(Js.Literal(argument.Value)));
                    }

                    // Return obj
                    initializerBlock.Return(Js.Reference("$obj$"));

                    attributeInstance = Wrap(initializerBlock);
                }
                result.Elements.Add(attributeInstance);
            }
            return MakeArray(result, Context.Instance.Compilation.CreateArrayTypeSymbol(Context.Instance.Attribute));
        }
Ejemplo n.º 6
0
        public JsExpressionStatement StoreClassCreateType(INamedTypeSymbol type)
        {
            var explicitName = type.GetAttributeValue<string>(Context.Instance.JsAttributeType, "Name");
            var fullTypeName = type.GetFullName();
            var baseType = type.BaseType != null ? Type(type.BaseType, true) : Js.Null();
            var body = new JsBlockStatement();
            body.Assign(Js.This().Member(SpecialNames.TypeField), 
                CreateObject(Context.Instance.TypeConstructor, Js.Primitive(type.Name), CreateAttributes(type)));

            TypeFlags typeFlags = 0;
            if (type.ContainingType == null)
            {
                switch (type.DeclaredAccessibility)
                {
                    case Accessibility.Public:
                        typeFlags |= TypeFlags.Public;
                        break;
                    case Accessibility.Internal:
                        typeFlags |= TypeFlags.Internal;
                        break;
                    default:
                        throw new Exception();
                }                
            }
            else
            {
                switch (type.DeclaredAccessibility)
                {
                    case Accessibility.Public:
                        typeFlags |= TypeFlags.Public;
                        break;
                    case Accessibility.Internal:
                        typeFlags |= TypeFlags.Internal;
                        break;
                    case Accessibility.Private:
                        typeFlags |= TypeFlags.Private;
                        break;
                    case Accessibility.Protected:
                        typeFlags |= TypeFlags.Protected;
                        break;
                    case Accessibility.ProtectedOrInternal:
                        typeFlags |= TypeFlags.Private | TypeFlags.Internal;
                        break;
                    default:
                        throw new Exception();
                }
            }
            if (type.TypeKind == TypeKind.Interface)
            {
                typeFlags |= TypeFlags.Interface;
            }
            else if (type.TypeKind == TypeKind.Class)
            {
                typeFlags |= TypeFlags.Class;
            }
            else if (type.TypeKind == TypeKind.Enum)
            {
                typeFlags |= TypeFlags.Enum;
            }
            if (type.IsAbstract)
            {
                typeFlags |= TypeFlags.Abstract;
            }
            else if (type.IsSealed)
            {
                typeFlags |= TypeFlags.Sealed;
            }
            if (type.IsValueType)
            {
                typeFlags |= TypeFlags.ValueType;
            }
            if (type.IsPrimitive())
            {
                typeFlags |= TypeFlags.Primitive;
            }
            if (type.IsGenericType || type.IsAnonymousTypeWithTypeParameters())
            {
                typeFlags |= TypeFlags.GenericType;
            }
            if (type.TypeParameters.Any())
            {
                typeFlags |= TypeFlags.GenericTypeDefenition;
            }
            if (type.TypeKind == TypeKind.TypeParameter)
            {
                typeFlags |= TypeFlags.GenericParameter;
            }

            var arguments = new List<JsExpression>
            {
                Js.Primitive(explicitName ?? fullTypeName),          // Param1: fullTypeName
                Js.Primitive((int)typeFlags),
                Type(type, true), 
                baseType,
                CreateInterfaceReferences(type),
                MakeArray(Js.Array(type.TypeParameters.Select(x => Js.Reference(x.Name)).Concat(type.GetAnonymousTypeParameters().Select(x => Js.Reference(x.Item2))).ToArray()), Context.Instance.TypeArray)
            };

            if (!Context.Instance.Compilation.Assembly.IsReflectionMinimized())
            {
                arguments.AddRange(new[]
                {
                    CreateFieldInfos(type),
                    CreateMethodInfos(type, false),
                    CreateMethodInfos(type, true),
                    CreatePropertyInfos(type),
                    CreateEventInfos(type)
                });
            }

            body.Express(Invoke(Js.This().Member(SpecialNames.TypeField), Context.Instance.TypeInit, arguments.ToArray()));
            body.Return(Js.This().Member(SpecialNames.TypeField));
            var result = StoreInType(SpecialNames.CreateType, Js.Function().Body(body).Compact());
            return result;
        }
Ejemplo n.º 7
0
        public JsBlockStatement CreateDefaultConstructor(BaseTypeDeclarationSyntax type)
        {
            var classType = transformer.model.GetDeclaredSymbol(type);

            var fullTypeName = type.GetFullName();
            var constructorBlock = new JsBlockStatement();

            if (fullTypeName != "System.Object")
            {
                constructorBlock.Express(InvokeParameterlessBaseClassConstructor(classType.BaseType));
            }

            if (type is ClassDeclarationSyntax)
            {
                constructorBlock.Aggregate(InitializeInstanceFields((ClassDeclarationSyntax)type));
            }

            var block = new JsBlockStatement();
            var constructorName = classType.GetDefaultConstructorName();
            block.Add(StoreInPrototype(constructorName, Js.Reference(SpecialNames.DefineConstructor).Invoke(
                Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                Js.Function().Body(constructorBlock))));

            return block;            
        }
Ejemplo n.º 8
0
        public bool TryCharUnaryExpression(SyntaxKind type, TypeInfo operandType, JsExpression operand, out JsExpression result)
        {
            if (Equals(operandType.Type, Context.Instance.Char))
            {
                switch (type)
                {
                    case SyntaxKind.PostDecrementExpression:
                    case SyntaxKind.PostIncrementExpression:
                    {
                        var old = Js.Variable("$old", operand);

                        var op = type == SyntaxKind.PostDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            old.GetReference().Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));

                        var block = new JsBlockStatement();
                        block.Local(old);
                        block.Express(result);
                        block.Return(old.GetReference());
                        result = Wrap(block);

                        return true;
                    }
                    case SyntaxKind.PreDecrementExpression:
                    case SyntaxKind.PreIncrementExpression:
                    {
                        var op = type == SyntaxKind.PreDecrementExpression ? JsBinaryOperator.Subtract : JsBinaryOperator.Add;
                        result = Js.Binary(
                            op, 
                            operand.Member("charCodeAt").Invoke(Js.Primitive(0)),
                            Js.Primitive(1)
                        );
                        result = operand.Assign(Js.Reference("String").Member("fromCharCode").Invoke(result));
                        return true;
                    }
                }
            }
            result = null;
            return false;
        }
Ejemplo n.º 9
0
        public JsInvocationExpression CreateMulticastDelegate(JsExpression target, JsExpression invocationList)
        {
            var delegateBody = new JsBlockStatement();
            var list = Js.Variable("$invocationList", invocationList);
            var i = Js.Variable("$i", Js.Primitive(0));
            delegateBody.Add(
                Js.For(
                    i, 
                    i.GetReference().LessThan(list.GetReference().Member("length")), 
                    i.GetReference().Increment()
                )
                .Body(list.GetReference().Index(i.GetReference()).Member("apply").Invoke(Js.Null(), Js.Reference("arguments")).Express()));

            var delegateExpression = Js.Function();
            delegateExpression.Body(delegateBody);
            var delegateVariable = Js.Variable("$delegate$", delegateExpression);

            var delegateType = invocationList.Index(Js.Primitive(0)).Member(SpecialNames.TypeField);

            var wrapper = new JsBlockStatement();
            wrapper.Local(list);
            wrapper.Local(delegateVariable);
            wrapper.Assign(delegateVariable.GetReference().Member("prototype"), Js.New(Type(Context.Instance.MulticastDelegateType)));
            wrapper.Invoke(Type(Context.Instance.ObjectType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(Type(Context.Instance.DelegateType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(Type(Context.Instance.MulticastDelegateType).Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Invoke(delegateType.Member(SpecialNames.TypeInitializer), delegateVariable.GetReference(), delegateVariable.GetReference());
            wrapper.Express(InvokeMethodAs(
                Context.Instance.MulticastDelegateConstructor, 
                delegateVariable.GetReference(), 
                target, 
                list.GetReference()));
            wrapper.Assign(delegateVariable.GetReference().Member(SpecialNames.TypeField), delegateType);
            wrapper.Return(delegateVariable.GetReference());

            return Wrap(wrapper);
        }