private static string CreateTypeArgumentName(TypeSymbol typeArgument) { if (typeArgument is GenericParameterSymbol parameterSymbol) { if (parameterSymbol.Owner is ClassSymbol) { return($"{DSharpStringResources.ScriptExportMember("getTypeArgument")}(this, '{typeArgument.FullGeneratedName}')"); } return($"{DSharpStringResources.GeneratedScript.GENERIC_ARGS_PARAMETER_NAME}['{typeArgument.FullGeneratedName}']"); } if (typeArgument.IsGeneric) { StringBuilder stringBuilder = new StringBuilder(); //Local method to recursively write the string. void Write(string value) => stringBuilder.Append(value); stringBuilder.Append(DSharpStringResources.ScriptExportMember("getGenericConstructor")); stringBuilder.Append("("); stringBuilder.Append(typeArgument.FullGeneratedName); stringBuilder.Append(", "); WriteGenericTypeArguments(Write, typeArgument.GenericArguments, typeArgument.GenericParameters); stringBuilder.Append(")"); return(stringBuilder.ToString()); } return(typeArgument.FullGeneratedName); }
private static void GenerateClassRegistrationScript(ScriptGenerator generator, ClassSymbol classSymbol) { ScriptTextWriter writer = generator.Writer; //class definition writer.Write($"{DSharpStringResources.ScriptExportMember("defineClass")}("); writer.Write(classSymbol.FullGeneratedName); writer.Write(", "); if (classSymbol.IsStaticClass) { writer.Write("null, "); } else { writer.Write(classSymbol.FullGeneratedName); writer.Write("$, "); } WriteConstructorParameters(classSymbol, writer); WriteBaseClass(classSymbol, writer); WriteInterfaces(writer, classSymbol.Interfaces); writer.Write(")"); }
private static void GenerateBaseInitializerExpression(ScriptGenerator generator, MemberSymbol symbol, BaseInitializerExpression expression) { ScriptTextWriter writer = generator.Writer; Debug.Assert(symbol.Parent is ClassSymbol); ClassSymbol baseClass = ((ClassSymbol)symbol.Parent).BaseClass; Debug.Assert(baseClass != null); if (baseClass.GenericArguments?.Any() ?? false) { writer.Write(DSharpStringResources.ScriptExportMember("getGenericConstructor")); writer.Write("("); writer.Write(baseClass.FullGeneratedName); writer.Write(", "); generator.WriteGenericTypeArgumentsMap(baseClass.GenericArguments, baseClass.GenericParameters); writer.Write(")"); } else { writer.Write(baseClass.FullGeneratedName); } writer.Write(".call(this"); if (expression.Parameters != null) { writer.Write(", "); GenerateExpressionList(generator, symbol, expression.Parameters); } writer.Write(")"); }
private static void GenerateInterfaceRegistrationScript(ScriptGenerator generator, InterfaceSymbol interfaceSymbol) { ScriptTextWriter writer = generator.Writer; writer.Write($"{DSharpStringResources.ScriptExportMember("defineInterface")}("); writer.Write(interfaceSymbol.FullGeneratedName); if (interfaceSymbol.Interfaces != null) { writer.Write(", ["); bool first = true; foreach (InterfaceSymbol inheritedInterface in interfaceSymbol.Interfaces) { if (!first) { writer.Write(", "); } writer.Write(inheritedInterface.FullGeneratedName); first = false; } writer.Write("]"); } writer.Write(")"); }
//TODO: Investigate removing these. private void ImportPseudoMembers(PseudoClassMembers memberSet, ClassSymbol classSymbol) { // Import pseudo members that go on the class but aren't defined in mscorlib.dll // These are meant to be used by internal compiler-generated transformations etc. // and aren't meant to be referenced directly in C# code. if (memberSet == PseudoClassMembers.Script) { AddScriptSymbolPseudoMembers(classSymbol); return; } if (memberSet == PseudoClassMembers.Arguments) { TypeSymbol objectType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Object), null, SymbolFilter.Types); Debug.Assert(objectType != null); IndexerSymbol indexer = new IndexerSymbol(classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static); indexer.SetScriptIndexer(); classSymbol.AddMember(indexer); return; } if (memberSet == PseudoClassMembers.Dictionary) { TypeSymbol intType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Int32), null, SymbolFilter.Types); Debug.Assert(intType != null); TypeSymbol stringType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(String), null, SymbolFilter.Types); Debug.Assert(stringType != null); // Define Dictionary.Keys MethodSymbol getKeysMethod = new MethodSymbol("GetKeys", classSymbol, symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static); getKeysMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keys")); classSymbol.AddMember(getKeysMethod); // Define Dictionary.Values MethodSymbol getValuesMethod = new MethodSymbol("GetValues", classSymbol, symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static); getValuesMethod.SetTransformName(DSharpStringResources.ScriptExportMember("values")); classSymbol.AddMember(getValuesMethod); // Define Dictionary.GetCount MethodSymbol countMethod = new MethodSymbol("GetKeyCount", classSymbol, intType, MemberVisibility.Public | MemberVisibility.Static); countMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keyCount")); classSymbol.AddMember(countMethod); } }
internal static string GetNodeTransformName(this ParseNodeList parseNodeList) { string dsharpMemberName = parseNodeList?.GetAttributeValue(DSharpStringResources.DSHARP_MEMBER_NAME_ATTRIBUTE); if (!string.IsNullOrEmpty(dsharpMemberName)) { return(DSharpStringResources.ScriptExportMember(dsharpMemberName)); } return(parseNodeList?.GetAttributeValue(DSharpStringResources.SCRIPT_ALIAS_ATTRIBUTE)); }
private static void GenerateEnumerationRegistrationScript( ScriptGenerator generator, EnumerationSymbol enumerationSymbol) { ScriptTextWriter writer = generator.Writer; writer.Write($"new {DSharpStringResources.ScriptExportMember("Enum")}("); writer.Write($"'{enumerationSymbol.FullGeneratedName}'"); writer.Write(", "); writer.Write(enumerationSymbol.FullGeneratedName); writer.Write(")"); }
private static void GenerateEnumeration(ScriptGenerator generator, EnumerationSymbol enumSymbol) { ScriptTextWriter writer = generator.Writer; string enumName = enumSymbol.FullGeneratedName; writer.Write("var "); writer.Write(enumName); writer.Write(" = new "); writer.Write(DSharpStringResources.ScriptExportMember("Enum")); writer.Write("('"); writer.Write(enumName); writer.Write("', "); writer.Write("{"); writer.Indent++; bool firstValue = true; foreach (MemberSymbol memberSymbol in enumSymbol.Members) { if (!(memberSymbol is EnumerationFieldSymbol fieldSymbol)) { continue; } if (firstValue == false) { writer.Write(", "); } writer.WriteLine(); writer.Write(fieldSymbol.GeneratedName); writer.Write(": "); if (enumSymbol.UseNamedValues) { writer.Write(Utility.QuoteString(enumSymbol.CreateNamedValue(fieldSymbol))); } else { writer.Write(fieldSymbol.Value); } firstValue = false; } writer.Indent--; writer.WriteLine(); writer.Write("});"); writer.WriteLine(); }
private static string CreateTypeArgumentName(TypeSymbol typeArgument, bool writeNameMap) { if (typeArgument.SymbolSet.ResolveIntrinsicType(IntrinsicType.Nullable).Name == typeArgument.Name) { return(CreateTypeArgumentName(typeArgument.GenericArguments.First(), writeNameMap)); } if (typeArgument is GenericParameterSymbol parameterSymbol) { if (writeNameMap) { return($"'{typeArgument.FullGeneratedName}'"); } if (parameterSymbol.Owner is ClassSymbol owner) { return($"{DSharpStringResources.ScriptExportMember("getTypeArgument")}(this, '{typeArgument.FullGeneratedName}', {owner.FullGeneratedName})"); } return($"{DSharpStringResources.GeneratedScript.GENERIC_ARGS_PARAMETER_NAME}['{typeArgument.FullGeneratedName}']"); } if (typeArgument.Type == SymbolType.Delegate) { return("Function"); } if (typeArgument.IsGeneric) { StringBuilder stringBuilder = new StringBuilder(); //Local method to recursively write the string. void Write(string value) => stringBuilder.Append(value); stringBuilder.Append(DSharpStringResources.ScriptExportMember("getGenericConstructor")); stringBuilder.Append("("); stringBuilder.Append(typeArgument.FullGeneratedName); stringBuilder.Append(", "); WriteGenericTypeArguments(Write, typeArgument.GenericArguments, typeArgument.GenericParameters); stringBuilder.Append(")"); return(stringBuilder.ToString()); } return(typeArgument.FullGeneratedName); }
private static void GeneratePropertySetter(ScriptGenerator generator, string typeName, PropertySymbol propertySymbol, ScriptTextWriter writer, bool instanceMember) { ParameterSymbol valueParameter = propertySymbol.Parameters[0]; if (instanceMember) { writer.Write("$set_"); writer.Write(propertySymbol.GeneratedName); writer.Write(": "); } else { writer.Write($"{DSharpStringResources.ScriptExportMember("createPropertySet")}("); writer.Write(typeName); writer.Write(", '"); writer.Write(propertySymbol.GeneratedName); writer.Write("', "); } writer.Write("function("); writer.Write(valueParameter.GeneratedName); writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, propertySymbol); } CodeGenerator.GenerateScript(generator, propertySymbol, /* getter */ false); writer.Write("return "); writer.Write(valueParameter.GeneratedName); writer.Write(";"); writer.WriteLine(); writer.Indent--; writer.Write("}"); if (instanceMember == false) { writer.WriteLine(");"); } }
public static string GetTransformedName(ICustomAttributeProvider attributeProvider) { CustomAttribute dsharpScriptMemberName = GetAttribute(attributeProvider, "System.Runtime.CompilerServices.DSharpScriptMemberNameAttribute"); if (dsharpScriptMemberName != null) { return(DSharpStringResources.ScriptExportMember(GetAttributeArgument(dsharpScriptMemberName))); } CustomAttribute scriptAliasAttribute = GetAttribute(attributeProvider, "System.Runtime.CompilerServices.ScriptAliasAttribute"); if (scriptAliasAttribute != null) { return(GetAttributeArgument(scriptAliasAttribute)); } return(null); }
private static void GenerateProperty(ScriptGenerator generator, string typeName, PropertySymbol propertySymbol) { if (propertySymbol.IsAbstract) { return; } ScriptTextWriter writer = generator.Writer; bool instanceMember = true; if ((propertySymbol.Visibility & MemberVisibility.Static) != 0) { instanceMember = false; } if (propertySymbol.HasGetter) { GeneratePropertyGetter(generator, typeName, propertySymbol, writer, instanceMember); } if (propertySymbol.HasSetter) { if (instanceMember && propertySymbol.HasGetter) { writer.WriteLine(","); } GeneratePropertySetter(generator, typeName, propertySymbol, writer, instanceMember); } if (propertySymbol.Visibility.HasFlag(MemberVisibility.Static) && propertySymbol.IsAutoProperty()) { writer.Write(DSharpStringResources.ScriptExportMember("defineProperty")); writer.Write($"({((ClassSymbol)propertySymbol.Parent).FullGeneratedName}, '{propertySymbol.GeneratedName}');"); writer.WriteLine(); } }
private static void GenerateBinaryExpression(ScriptGenerator generator, MemberSymbol symbol, BinaryExpression expression) { ScriptTextWriter writer = generator.Writer; if (expression.Operator == Operator.Equals) { if (expression.LeftOperand is PropertyExpression propExpression) { Debug.Assert(propExpression.Type == ExpressionType.PropertySet); if (propExpression.ObjectReference is BaseExpression) { ClassSymbol classSymbol = (ClassSymbol)symbol.Parent; writer.Write($"{DSharpStringResources.ScriptExportMember("baseProperty")}("); writer.Write(classSymbol.FullGeneratedName); writer.Write(", '"); writer.Write(propExpression.Property.GeneratedName); writer.Write("').set.call("); writer.Write(generator.CurrentImplementation.ThisIdentifier); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } else { GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write("."); writer.Write(propExpression.Property.GeneratedName); writer.Write(" = "); GenerateExpression(generator, symbol, expression.RightOperand); } propExpression.Property.IncrementReferenceCount(); return; } if (expression.LeftOperand is IndexerExpression indexExpression) { IndexerSymbol indexerSymbol = indexExpression.Indexer; if (!indexerSymbol.UseScriptIndexer) { Debug.Assert(indexExpression.Type == ExpressionType.Indexer); if (indexExpression.ObjectReference is BaseExpression objectReference) { writer.Write(objectReference.EvaluatedType.FullGeneratedName); writer.Write(".prototype.set_"); writer.Write(indexerSymbol.GeneratedName); writer.Write(".call("); writer.Write(generator.CurrentImplementation.ThisIdentifier); writer.Write(", "); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } else { GenerateExpression(generator, symbol, indexExpression.ObjectReference); writer.Write(".set_"); writer.Write(indexerSymbol.GeneratedName); writer.Write("("); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); } indexExpression.Indexer.IncrementReferenceCount(); return; } else if (indexerSymbol.Parent is TypeSymbol typeSymbol && !typeSymbol.IsNativeArray) { writer.Write($"ss.setItem("); GenerateExpression(generator, symbol, indexExpression.ObjectReference); writer.Write(", "); GenerateExpressionList(generator, symbol, indexExpression.Indices); writer.Write(", "); GenerateExpression(generator, symbol, expression.RightOperand); writer.Write(")"); return; } } } else if (expression.Operator == Operator.PlusEquals || expression.Operator == Operator.MinusEquals || expression.Operator == Operator.MultiplyEquals || expression.Operator == Operator.DivideEquals || expression.Operator == Operator.ModEquals || expression.Operator == Operator.BitwiseOrEquals || expression.Operator == Operator.BitwiseAndEquals || expression.Operator == Operator.BitwiseXorEquals || expression.Operator == Operator.ShiftLeftEquals || expression.Operator == Operator.ShiftRightEquals || expression.Operator == Operator.UnsignedShiftRightEquals) { if (expression.LeftOperand is PropertyExpression propExpression) { Debug.Assert(propExpression.Type == ExpressionType.PropertyGet); GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write("."); writer.Write(propExpression.Property.GeneratedName); writer.Write(" = "); GenerateExpression(generator, symbol, propExpression.ObjectReference); writer.Write(OperatorConverter.OperatorToString(expression.Operator - 1)); GenerateExpression(generator, symbol, expression.RightOperand); propExpression.Property.IncrementReferenceCount(); return; } } else if (expression.Operator == Operator.Is || expression.Operator == Operator.As) { TypeExpression typeExpression = expression.RightOperand as TypeExpression; Debug.Assert(typeExpression != null); writer.Write(DSharpStringResources.ScriptExportMember(string.Empty)); if (expression.Operator == Operator.Is) { writer.Write("canCast("); } else { writer.Write("safeCast("); } GenerateExpression(generator, symbol, expression.LeftOperand); writer.Write(", "); writer.Write(typeExpression.AssociatedType.FullGeneratedName); writer.Write(")"); typeExpression.AssociatedType.IncrementReferenceCount(); return; } else if (expression.Operator == Operator.EqualEqualEqual || expression.Operator == Operator.NotEqualEqual) { if (expression.RightOperand is LiteralExpression literalExpression) { // Optimize generated script to perform loose equality checks for false-y values // (null, false, 0, empty string) // TODO: This should really be happening at compilation time, rather than generation // time. Because this is happening at generation time, we get something like // if (!!x) when if(x) would suffice just so we can get // foo(!!x) where foo is a method expecting a boolean. // Doing this at compilation time would allow handling if scenarios specially. bool optimizable = false; bool checkForFalse = false; if (literalExpression.Value is bool compareValue) { optimizable = true; if (compareValue && expression.Operator == Operator.NotEqualEqual || !compareValue && expression.Operator == Operator.EqualEqualEqual) { checkForFalse = true; } } else if (literalExpression.Value is int i && i == 0) { optimizable = true; checkForFalse = expression.Operator == Operator.EqualEqualEqual; } else if (literalExpression.Value is string s && s == string.Empty) { optimizable = true; checkForFalse = expression.Operator == Operator.EqualEqualEqual; } if (optimizable) { bool parenthesize = false; writer.Write(checkForFalse ? "!" : "!!"); if (expression.LeftOperand.Parenthesized == false && (expression.LeftOperand.Type == ExpressionType.Binary || expression.LeftOperand.Type == ExpressionType.Conditional || expression.LeftOperand.Type == ExpressionType.InlineScript)) { parenthesize = true; writer.Write("("); } GenerateExpression(generator, symbol, expression.LeftOperand); if (parenthesize) { writer.Write(")"); } return; } } }
private static void GenerateMethod(ScriptGenerator generator, string typeName, MethodSymbol methodSymbol) { if (methodSymbol.IsAbstract) { return; } ScriptTextWriter writer = generator.Writer; bool instanceMember = (methodSymbol.Visibility & MemberVisibility.Static) == 0; if (instanceMember == false) { writer.Write(typeName); writer.Write("."); } writer.Write(methodSymbol.GeneratedMemberName); if (instanceMember) { writer.Write(": "); } else { writer.Write(" = "); } bool hasParams = HasParamsModifier(methodSymbol); if (hasParams) { writer.Write($"{DSharpStringResources.ScriptExportMember("paramsGenerator")}("); writer.Write("{0}, ", methodSymbol.GetGeneratedParamsCount()); } writer.Write("function("); WriteParameters(methodSymbol, writer, true); writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, methodSymbol); } CodeGenerator.GenerateScript(generator, methodSymbol); writer.Indent--; writer.Write("}"); if (hasParams) { writer.Write(")"); } if (instanceMember == false) { writer.WriteLine(";"); } }
private static void GenerateEvent(ScriptGenerator generator, string typeName, EventSymbol eventSymbol) { ScriptTextWriter writer = generator.Writer; ParameterSymbol valueParameter = eventSymbol.Parameters[0]; string eventName = eventSymbol.GeneratedName; string fieldName = eventName; if (eventSymbol.DefaultImplementation) { fieldName = "__" + Utility.CreateCamelCaseName(eventSymbol.Name); Debug.Assert(eventSymbol.Parent.Type == SymbolType.Class); Symbol fieldSymbol = ((ClassSymbol)eventSymbol.Parent).GetMember(fieldName); Debug.Assert(fieldSymbol != null && fieldSymbol.Type == SymbolType.Field); fieldName = fieldSymbol.GeneratedName; } string fieldReference; if ((eventSymbol.Visibility & MemberVisibility.Static) == 0) { fieldReference = "this."; } else { fieldReference = typeName + "."; } fieldReference += fieldName; bool instanceMember = true; if ((eventSymbol.Visibility & MemberVisibility.Static) != 0) { instanceMember = false; writer.Write(typeName); writer.Write("."); } writer.Write("add_"); writer.Write(eventName); if (instanceMember) { writer.Write(": "); } else { writer.Write(" = "); } writer.Write("function("); writer.Write(valueParameter.GeneratedName); writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, eventSymbol); } if (eventSymbol.DefaultImplementation) { writer.Write(fieldReference); writer.Write($" = {DSharpStringResources.ScriptExportMember("bindAdd")}("); writer.Write(fieldReference); writer.Write(", "); writer.Write(valueParameter.GeneratedName); writer.WriteLine(");"); } else { CodeGenerator.GenerateScript(generator, eventSymbol, /* add */ true); } writer.Indent--; writer.Write("}"); if (instanceMember == false) { writer.WriteLine(";"); } if (instanceMember) { writer.WriteLine(","); } else { writer.Write(typeName); writer.Write("."); } writer.Write("remove_"); writer.Write(eventName); if (instanceMember) { writer.Write(": "); } else { writer.Write(" = "); } writer.Write("function("); writer.Write(valueParameter.GeneratedName); writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, eventSymbol); } if (eventSymbol.DefaultImplementation) { writer.Write(fieldReference); writer.Write($" = {DSharpStringResources.ScriptExportMember("bindSub")}("); writer.Write(fieldReference); writer.Write(", "); writer.Write(valueParameter.GeneratedName); writer.WriteLine(");"); } else { CodeGenerator.GenerateScript(generator, eventSymbol, /* add */ false); } writer.Indent--; writer.Write("}"); if (instanceMember == false) { writer.WriteLine(";"); } }
public void GenerateScript(SymbolSet symbolSet) { Debug.Assert(symbolSet != null); List <TypeSymbol> types = new List <TypeSymbol>(); List <TypeSymbol> publicTypes = new List <TypeSymbol>(); List <TypeSymbol> internalTypes = new List <TypeSymbol>(); bool hasNonModuleInternalTypes = false; foreach (NamespaceSymbol namespaceSymbol in symbolSet.Namespaces) { if (namespaceSymbol.HasApplicationTypes) { foreach (TypeSymbol type in namespaceSymbol.Types) { if (type.IsApplicationType == false) { continue; } if (type.Type == SymbolType.Delegate) { // Nothing needs to be generated for delegate types. continue; } if (type.Type == SymbolType.Enumeration && (type.IsPublic == false || ((EnumerationSymbol)type).Constants)) { // Internal enums can be skipped since their values have been inlined. // Public enums marked as constants can also be skipped since their // values will always be inlined. continue; } types.Add(type); if (type.IsPublic) { publicTypes.Add(type); } else { if (type.Type != SymbolType.Class || ((ClassSymbol)type).IsModuleClass == false) { hasNonModuleInternalTypes = true; } internalTypes.Add(type); } } } } // Sort the types, so similar types of types are grouped, and parent classes // come before derived classes. IComparer <TypeSymbol> typeComparer = new TypeComparer(); types = types.OrderBy(t => t, typeComparer).ToList(); publicTypes = publicTypes.OrderBy(t => t, typeComparer).ToList(); internalTypes = internalTypes.OrderBy(t => t, typeComparer).ToList(); bool initialIndent = false; if (string.IsNullOrEmpty(Options.ScriptInfo.Template) == false) { int scriptIndex = Options.ScriptInfo.Template.IndexOf("{script}"); if (scriptIndex > 0 && Options.ScriptInfo.Template[scriptIndex - 1] == ' ') { // Heuristic to turn on initial indent: // The script template has a space prior to {script}, i.e. {script} is not the // first thing on a line within the template. initialIndent = true; } } if (initialIndent) { Writer.Indent++; } foreach (TypeSymbol type in types) { TypeGenerator.GenerateScript(this, type); } bool generateModule = publicTypes.Count != 0 || internalTypes.Count != 0 && hasNonModuleInternalTypes; if (generateModule) { Writer.Write($"var $exports = {DSharpStringResources.ScriptExportMember("module")}('"); Writer.Write(symbolSet.ScriptName); Writer.Write("',"); if (internalTypes.Count != 0 && hasNonModuleInternalTypes) { Writer.WriteLine(); Writer.Indent++; Writer.WriteLine("{"); Writer.Indent++; bool firstType = true; foreach (TypeSymbol type in internalTypes) { if (type.Type == SymbolType.Class && (((ClassSymbol)type).IsExtenderClass || ((ClassSymbol)type).IsModuleClass)) { continue; } if (type.Type == SymbolType.Record && ((RecordSymbol)type).Constructor == null) { continue; } if (firstType == false) { Writer.WriteLine(","); } TypeGenerator.GenerateRegistrationScript(this, type); firstType = false; } Writer.Indent--; Writer.WriteLine(); Writer.Write("},"); Writer.Indent--; } else { Writer.Write(" null,"); } if (publicTypes.Count != 0) { Writer.WriteLine(); Writer.Indent++; Writer.WriteLine("{"); Writer.Indent++; bool firstType = true; foreach (TypeSymbol type in publicTypes) { if (type.Type == SymbolType.Class && ((ClassSymbol)type).IsExtenderClass) { continue; } if (firstType == false) { Writer.WriteLine(","); } TypeGenerator.GenerateRegistrationScript(this, type); firstType = false; } Writer.Indent--; Writer.WriteLine(); Writer.Write("}"); Writer.Indent--; } else { Writer.Write(" null"); } Writer.WriteLine(");"); Writer.WriteLine(); } foreach (TypeSymbol type in types) { if (type.Type == SymbolType.Class) { TypeGenerator.GenerateClassConstructorScript(this, (ClassSymbol)type); } } if (initialIndent) { Writer.Indent--; } }
private static void GenerateClassRegistrationScript(ScriptGenerator generator, ClassSymbol classSymbol) { ScriptTextWriter writer = generator.Writer; //class definition writer.Write($"{DSharpStringResources.ScriptExportMember("defineClass")}("); writer.Write(classSymbol.FullGeneratedName); writer.Write(", "); if (classSymbol.IsStaticClass) { writer.Write("null, "); } else { writer.Write(classSymbol.FullGeneratedName); writer.Write("$, "); } //constructor params writer.Write("["); if (classSymbol.Constructor != null && classSymbol.Constructor.Parameters != null) { bool firstParameter = true; foreach (ParameterSymbol parameterSymbol in classSymbol.Constructor.Parameters) { if (firstParameter == false) { writer.Write(", "); } TypeSymbol parameterType = parameterSymbol.ValueType; string parameterTypeName = GetParameterTypeName(parameterType); writer.Write(parameterTypeName); firstParameter = false; } } writer.Write("], "); //base class if (classSymbol.BaseClass == null) { // TODO: We need to introduce the notion of a base class that only exists in the metadata // and not at runtime. At that point this check of IsTestClass can be generalized. writer.Write("null"); } else { writer.Write(classSymbol.BaseClass.FullGeneratedName); } //interfaces if (classSymbol.Interfaces != null) { writer.Write(", ["); bool first = true; foreach (InterfaceSymbol inheritedInterface in classSymbol.Interfaces) { if (!first) { writer.Write(", "); } string parameterTypeName = GetParameterTypeName(inheritedInterface); writer.Write(parameterTypeName); first = false; } writer.Write("]"); } writer.Write(")"); }
private static void GenerateMethod(ScriptGenerator generator, string typeName, MethodSymbol methodSymbol) { if (methodSymbol.IsAbstract) { return; } ScriptTextWriter writer = generator.Writer; bool instanceMember = (methodSymbol.Visibility & MemberVisibility.Static) == 0; if (instanceMember == false) { if (methodSymbol.IsExtension) { string extendee = null; if (methodSymbol.Parent.Type == SymbolType.Class) { extendee = ((ClassSymbol)methodSymbol.Parent).Extendee; } if (string.IsNullOrEmpty(extendee)) { extendee = "this"; } writer.Write(extendee); } else { writer.Write(typeName); } writer.Write("."); } writer.Write(methodSymbol.GeneratedMemberName); if (instanceMember) { writer.Write(": "); } else { writer.Write(" = "); } bool hasParams = HasParamsModifier(methodSymbol); if (hasParams) { writer.Write($"{DSharpStringResources.ScriptExportMember("paramsGenerator")}("); writer.Write("{0}, ", methodSymbol.Parameters.Count - 1); } writer.Write("function("); WriteParameters(methodSymbol, writer); writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, methodSymbol); } CodeGenerator.GenerateScript(generator, methodSymbol); writer.Indent--; writer.Write("}"); if (hasParams) { writer.Write(")"); } if (instanceMember == false) { writer.WriteLine(";"); } }
private static void GenerateClassConstructor(ScriptGenerator generator, ClassSymbol classSymbol, ScriptTextWriter writer, string name) { var ctorSymbol = classSymbol.Constructor; if (HasParamsModifier(ctorSymbol)) { writer.Write($"var {name} = ss.namedFunction('{name}',"); writer.Write($"{DSharpStringResources.ScriptExportMember("paramsGenerator")}("); writer.Write($"{ctorSymbol.GetGeneratedParamsCount()}, function"); } else { writer.Write("function "); writer.Write(name); } writer.Write("("); if (ctorSymbol != null && ctorSymbol.Parameters != null) { bool firstParameter = true; foreach (ParameterSymbol parameterSymbol in ctorSymbol.Parameters) { if (firstParameter == false) { writer.Write(", "); } writer.Write(parameterSymbol.GeneratedName); firstParameter = false; } } writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, classSymbol); } foreach (var property in GetNonReadonlyAutoProperties(classSymbol)) { writer.Write(DSharpStringResources.ScriptExportMember("defineProperty")); writer.Write($"(this, '{property.GeneratedName}', "); var initialValueExpression = Compiler.ImplementationBuilder.GetDefaultValueExpression(property.AssociatedType, property.SymbolSet); ExpressionGenerator.GenerateLiteralExpression(generator, property, initialValueExpression); writer.Write(");"); writer.WriteLine(); } foreach (MemberSymbol memberSymbol in classSymbol.Members) { if (memberSymbol.Type == SymbolType.Field && (memberSymbol.Visibility & MemberVisibility.Static) == 0) { FieldSymbol fieldSymbol = (FieldSymbol)memberSymbol; if (fieldSymbol.HasInitializer) { writer.Write("this."); writer.Write(fieldSymbol.GeneratedName); writer.Write(" = "); CodeGenerator.GenerateScript(generator, fieldSymbol); writer.Write(";"); writer.WriteLine(); } } } if (ctorSymbol != null) { CodeGenerator.GenerateScript(generator, ctorSymbol); } else if (classSymbol.BaseClass is ClassSymbol baseClass) { ExpressionGenerator.WriteFullTypeName(writer, baseClass); writer.WriteLine(".call(this);"); } writer.Indent--; writer.WriteLine("}"); if (HasParamsModifier(ctorSymbol)) { writer.WriteLine($"));"); } }
private void AddScriptSymbolPseudoMembers(ClassSymbol classSymbol) { var symbolTable = symbols.SystemNamespace; TypeSymbol objectType = symbolTable.FindSymbol <TypeSymbol>(nameof(Object), null, SymbolFilter.Types); TypeSymbol stringType = symbolTable.FindSymbol <TypeSymbol>(nameof(String), null, SymbolFilter.Types); TypeSymbol boolType = symbolTable.FindSymbol <TypeSymbol>(nameof(Boolean), null, SymbolFilter.Types); TypeSymbol dateType = symbolTable.FindSymbol <TypeSymbol>("Date", null, SymbolFilter.Types); TypeSymbol voidType = symbols.ResolveIntrinsicType(IntrinsicType.Void); TypeSymbol typeSymbol = symbols.ResolveIntrinsicType(IntrinsicType.Type); Debug.Assert(objectType != null); Debug.Assert(stringType != null); Debug.Assert(boolType != null); Debug.Assert(dateType != null); Debug.Assert(voidType != null); // Enumerate - IEnumerable.GetEnumerator gets mapped to this MethodSymbol enumerateMethod = new MethodSymbol("Enumerate", classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static); enumerateMethod.SetTransformName(DSharpStringResources.ScriptExportMember("enumerate")); enumerateMethod.AddParameter(new ParameterSymbol("obj", enumerateMethod, objectType, ParameterMode.In)); classSymbol.AddMember(enumerateMethod); // TypeName - Type.Name gets mapped to this MethodSymbol typeNameMethod = new MethodSymbol("GetTypeName", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static); typeNameMethod.SetTransformName(DSharpStringResources.ScriptExportMember("typeName")); typeNameMethod.AddParameter(new ParameterSymbol("obj", typeNameMethod, objectType, ParameterMode.In)); classSymbol.AddMember(typeNameMethod); // CompareDates - Date equality checks get converted to call to compareDates MethodSymbol compareDatesMethod = new MethodSymbol("CompareDates", classSymbol, boolType, MemberVisibility.Public | MemberVisibility.Static); compareDatesMethod.SetTransformName(DSharpStringResources.ScriptExportMember("compareDates")); compareDatesMethod.AddParameter(new ParameterSymbol("d1", compareDatesMethod, dateType, ParameterMode.In)); compareDatesMethod.AddParameter(new ParameterSymbol("d2", compareDatesMethod, dateType, ParameterMode.In)); classSymbol.AddMember(compareDatesMethod); //createReadonlyPropertyMethod - setups a replacement for readonly assignment expressions to generate readonly properties. MethodSymbol createReadonlyPropertyMethod = new MethodSymbol("CreateReadonlyProperty", classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static); createReadonlyPropertyMethod.SetTransformName(DSharpStringResources.ScriptExportMember("createReadonlyProperty")); createReadonlyPropertyMethod.AddParameter(new ParameterSymbol("instance", createReadonlyPropertyMethod, objectType, ParameterMode.In)); createReadonlyPropertyMethod.AddParameter(new ParameterSymbol("propertyName", createReadonlyPropertyMethod, stringType, ParameterMode.In)); createReadonlyPropertyMethod.AddParameter(new ParameterSymbol("value", createReadonlyPropertyMethod, objectType, ParameterMode.In)); classSymbol.AddMember(createReadonlyPropertyMethod); MethodSymbol definePropertyMethod = new MethodSymbol("DefineMethod", classSymbol, voidType, MemberVisibility.Public | MemberVisibility.Static); definePropertyMethod.SetTransformName(DSharpStringResources.ScriptExportMember("defineProperty")); definePropertyMethod.AddParameter(new ParameterSymbol("instance", definePropertyMethod, objectType, ParameterMode.In)); definePropertyMethod.AddParameter(new ParameterSymbol("propertyName", definePropertyMethod, stringType, ParameterMode.In)); classSymbol.AddMember(definePropertyMethod); MethodSymbol getGenericConstructorMethod = new MethodSymbol("getGenericConstructor", classSymbol, typeSymbol, MemberVisibility.Public | MemberVisibility.Static); getGenericConstructorMethod.SetTransformName(DSharpStringResources.ScriptExportMember("getGenericConstructor")); getGenericConstructorMethod.AddParameter( new ParameterSymbol("ctorMethod", getGenericConstructorMethod, typeSymbol, ParameterMode.In)); getGenericConstructorMethod.AddParameter( new ParameterSymbol("typeArguments", getGenericConstructorMethod, objectType, ParameterMode.In)); classSymbol.AddMember(getGenericConstructorMethod); MethodSymbol getTypeArgument = new MethodSymbol("getTypeArgument", classSymbol, typeSymbol, MemberVisibility.Public | MemberVisibility.Static); getTypeArgument.SetTransformName(DSharpStringResources.ScriptExportMember("getTypeArgument")); getTypeArgument.AddParameter( new ParameterSymbol("instance", getTypeArgument, objectType, ParameterMode.In)); getTypeArgument.AddParameter( new ParameterSymbol("typeArgumentName", getTypeArgument, stringType, ParameterMode.In)); getTypeArgument.AddParameter( new ParameterSymbol("templateType", getTypeArgument, typeSymbol, ParameterMode.In)); classSymbol.AddMember(getTypeArgument); MethodSymbol getGenericTemplateMethod = new MethodSymbol("getGenericTemplate", classSymbol, typeSymbol, MemberVisibility.Public | MemberVisibility.Static); getGenericTemplateMethod.SetTransformName(DSharpStringResources.ScriptExportMember("getGenericTemplate")); getGenericTemplateMethod.AddParameter( new ParameterSymbol("ctorMethod", getGenericTemplateMethod, typeSymbol, ParameterMode.In)); getGenericTemplateMethod.AddParameter( new ParameterSymbol("typeParameters", getGenericTemplateMethod, objectType, ParameterMode.In)); classSymbol.AddMember(getGenericTemplateMethod); }
private void GenerateModuleExports(SymbolSet symbolSet, IEnumerable <TypeSymbol> types) { if (!types.Any()) { return; } IEnumerable <TypeSymbol> publicTypes = types.Where(type => type.IsPublic); IEnumerable <TypeSymbol> internalTypes = types.Where(type => type.IsInternal); Writer.Write($"var $exports = {DSharpStringResources.ScriptExportMember("module")}('"); Writer.Write(symbolSet.ScriptName); Writer.Write("',"); if (internalTypes.Any()) { Writer.WriteLine(); Writer.Indent++; Writer.WriteLine("{"); Writer.Indent++; bool firstType = true; foreach (TypeSymbol type in internalTypes) { if (type.Type == SymbolType.Record && ((RecordSymbol)type).Constructor == null) { continue; } if (firstType == false) { Writer.WriteLine(","); } TypeGenerator.GenerateRegistrationScript(this, type); firstType = false; } Writer.Indent--; Writer.WriteLine(); Writer.Write("},"); Writer.Indent--; } else { Writer.Write(" null,"); } if (publicTypes.Any()) { Writer.WriteLine(); Writer.Indent++; Writer.WriteLine("{"); Writer.Indent++; bool firstType = true; foreach (TypeSymbol type in publicTypes) { if (firstType == false) { Writer.WriteLine(","); } TypeGenerator.GenerateRegistrationScript(this, type); firstType = false; } Writer.Indent--; Writer.WriteLine(); Writer.Write("}"); Writer.Indent--; } else { Writer.Write(" null"); } Writer.WriteLine(");"); Writer.WriteLine(); }
private static void GenerateClassConstructor(ScriptGenerator generator, ClassSymbol classSymbol, ScriptTextWriter writer, string name) { writer.Write("function "); writer.Write(name); writer.Write("("); if (classSymbol.Constructor != null && classSymbol.Constructor.Parameters != null) { bool firstParameter = true; foreach (ParameterSymbol parameterSymbol in classSymbol.Constructor.Parameters) { if (firstParameter == false) { writer.Write(", "); } writer.Write(parameterSymbol.GeneratedName); firstParameter = false; } } writer.WriteLine(") {"); writer.Indent++; if (generator.Options.EnableDocComments) { DocCommentGenerator.GenerateComment(generator, classSymbol); } foreach (var property in GetNonReadonlyAutoProperties(classSymbol)) { writer.Write(DSharpStringResources.ScriptExportMember("defineProperty")); writer.Write($"(this, '{property.GeneratedName}');"); writer.WriteLine(); } foreach (MemberSymbol memberSymbol in classSymbol.Members) { if (memberSymbol.Type == SymbolType.Field && (memberSymbol.Visibility & MemberVisibility.Static) == 0) { FieldSymbol fieldSymbol = (FieldSymbol)memberSymbol; if (fieldSymbol.HasInitializer) { writer.Write("this."); writer.Write(fieldSymbol.GeneratedName); writer.Write(" = "); CodeGenerator.GenerateScript(generator, fieldSymbol); writer.Write(";"); writer.WriteLine(); } } } if (classSymbol.Constructor != null) { CodeGenerator.GenerateScript(generator, classSymbol.Constructor); } else if (classSymbol.BaseClass != null) { writer.Write(classSymbol.BaseClass.FullGeneratedName); writer.Write(".call(this);"); writer.WriteLine(); } writer.Indent--; writer.WriteLine("}"); }
//TODO: Investigate removing these. private void ImportPseudoMembers(PseudoClassMembers memberSet, ClassSymbol classSymbol) { // Import pseudo members that go on the class but aren't defined in mscorlib.dll // These are meant to be used by internal compiler-generated transformations etc. // and aren't meant to be referenced directly in C# code. if (memberSet == PseudoClassMembers.Script) { TypeSymbol objectType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol("Object", null, SymbolFilter.Types); Debug.Assert(objectType != null); TypeSymbol stringType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol("String", null, SymbolFilter.Types); Debug.Assert(stringType != null); TypeSymbol boolType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol("Boolean", null, SymbolFilter.Types); Debug.Assert(boolType != null); TypeSymbol dateType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol("Date", null, SymbolFilter.Types); Debug.Assert(dateType != null); // Enumerate - IEnumerable.GetEnumerator gets mapped to this MethodSymbol enumerateMethod = new MethodSymbol("Enumerate", classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static); enumerateMethod.SetTransformName(DSharpStringResources.ScriptExportMember("enumerate")); enumerateMethod.AddParameter(new ParameterSymbol("obj", enumerateMethod, objectType, ParameterMode.In)); classSymbol.AddMember(enumerateMethod); // TypeName - Type.Name gets mapped to this MethodSymbol typeNameMethod = new MethodSymbol("GetTypeName", classSymbol, stringType, MemberVisibility.Public | MemberVisibility.Static); typeNameMethod.SetTransformName(DSharpStringResources.ScriptExportMember("typeName")); typeNameMethod.AddParameter(new ParameterSymbol("obj", typeNameMethod, objectType, ParameterMode.In)); classSymbol.AddMember(typeNameMethod); // CompareDates - Date equality checks get converted to call to compareDates MethodSymbol compareDatesMethod = new MethodSymbol("CompareDates", classSymbol, boolType, MemberVisibility.Public | MemberVisibility.Static); compareDatesMethod.SetTransformName(DSharpStringResources.ScriptExportMember("compareDates")); compareDatesMethod.AddParameter(new ParameterSymbol("d1", compareDatesMethod, dateType, ParameterMode.In)); compareDatesMethod.AddParameter(new ParameterSymbol("d2", compareDatesMethod, dateType, ParameterMode.In)); classSymbol.AddMember(compareDatesMethod); return; } if (memberSet == PseudoClassMembers.Arguments) { TypeSymbol objectType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Object), null, SymbolFilter.Types); Debug.Assert(objectType != null); IndexerSymbol indexer = new IndexerSymbol(classSymbol, objectType, MemberVisibility.Public | MemberVisibility.Static); indexer.SetScriptIndexer(); classSymbol.AddMember(indexer); return; } if (memberSet == PseudoClassMembers.Dictionary) { TypeSymbol intType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(Int32), null, SymbolFilter.Types); Debug.Assert(intType != null); TypeSymbol stringType = (TypeSymbol)((ISymbolTable)symbols.SystemNamespace).FindSymbol(nameof(String), null, SymbolFilter.Types); Debug.Assert(stringType != null); // Define Dictionary.Keys MethodSymbol getKeysMethod = new MethodSymbol("GetKeys", classSymbol, symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static); getKeysMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keys")); classSymbol.AddMember(getKeysMethod); // Define Dictionary.Values MethodSymbol getValuesMethod = new MethodSymbol("GetValues", classSymbol, symbols.CreateArrayTypeSymbol(stringType), MemberVisibility.Public | MemberVisibility.Static); getValuesMethod.SetTransformName(DSharpStringResources.ScriptExportMember("values")); classSymbol.AddMember(getValuesMethod); // Define Dictionary.GetCount MethodSymbol countMethod = new MethodSymbol("GetKeyCount", classSymbol, intType, MemberVisibility.Public | MemberVisibility.Static); countMethod.SetTransformName(DSharpStringResources.ScriptExportMember("keyCount")); classSymbol.AddMember(countMethod); } }