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