protected virtual void EmitOperatorGroup(List <OperatorDeclaration> group) { if (group.Count == 1) { if (!group[0].Body.IsNull) { Emitter.VisitOperatorDeclaration(group[0]); } } else { var name = group[0].Name; var methodsDef = Emitter.GetTypeDefinition().Methods.Where(m => m.Name == name); Emitter.MethodsGroup = methodsDef; Emitter.MethodsGroupBuilder = new Dictionary <int, StringBuilder>(); foreach (var method in group) { if (!method.Body.IsNull) { Emitter.VisitOperatorDeclaration(method); } } Emitter.MethodsGroup = null; Emitter.MethodsGroupBuilder = null; } }
protected virtual void EmitMethodsGroup(List <MethodDeclaration> group) { if (group.Count == 1) { if ((!group[0].Body.IsNull || Emitter.GetScript(group[0]) != null) && (!StaticBlock || !Helpers.IsEntryPointMethod(Emitter, group[0]))) { Emitter.VisitMethodDeclaration(group[0]); } } else { var typeDef = Emitter.GetTypeDefinition(); var name = group[0].Name; var methodsDef = typeDef.Methods.Where(m => m.Name == name); Emitter.MethodsGroup = methodsDef; Emitter.MethodsGroupBuilder = new Dictionary <int, StringBuilder>(); foreach (var method in group) { if (!method.Body.IsNull && (!StaticBlock || !Helpers.IsEntryPointMethod(Emitter, group[0]))) { Emitter.VisitMethodDeclaration(method); } } Emitter.MethodsGroup = null; Emitter.MethodsGroupBuilder = null; } }
private void AcceptLeftExpression(Expression left, ResolveResult rr) { if (!Emitter.InConstructor || !(rr is MemberResolveResult mrr) || !(mrr.Member is IProperty) || mrr.Member.IsStatic || mrr.Member.DeclaringTypeDefinition == null || !mrr.Member.DeclaringTypeDefinition.Equals(Emitter.TypeInfo.Type)) { left.AcceptVisitor(Emitter); } else { var property = (IProperty)mrr.Member; var proto = mrr.IsVirtualCall || property.IsVirtual || property.IsOverride; var td = Emitter.GetTypeDefinition(); var prop = td.Properties.FirstOrDefault(p => p.Name == mrr.Member.Name); if (proto && prop != null && prop.SetMethod == null) { var name = OverloadsCollection.Create(Emitter, mrr.Member).GetOverloadName(); Write(JS.Types.H5.ENSURE_BASE_PROPERTY + "(this, \"" + name + "\""); if (Emitter.Validator.IsExternalType(property.DeclaringTypeDefinition) && !Emitter.Validator.IsH5Class(property.DeclaringTypeDefinition)) { Write(", \"" + H5Types.ToJsName(property.DeclaringType, Emitter, isAlias: true) + "\""); } Write(")"); WriteDot(); var alias = H5Types.ToJsName(mrr.Member.DeclaringType, Emitter, isAlias: true); if (alias.StartsWith("\"")) { alias = alias.Insert(1, "$"); name = alias + "+\"$" + name + "\""; WriteIdentifier(name, false); } else { name = "$" + alias + "$" + name; WriteIdentifier(name); } } else { left.AcceptVisitor(Emitter); } } }
protected virtual void EmitInstantiableBlock() { if (TypeInfo.IsEnum) { if (Emitter.GetTypeDefinition(TypeInfo.Type) .CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute")) { EnsureComma(); Write(JS.Fields.FLAGS + ": true"); Emitter.Comma = true; } var etype = TypeInfo.Type.GetDefinition().EnumUnderlyingType; var enumMode = Helpers.EnumEmitMode(TypeInfo.Type); var isString = enumMode >= 3 && enumMode <= 6; if (isString) { etype = Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } if (!etype.IsKnownType(KnownTypeCode.Int32)) { EnsureComma(); Write(JS.Fields.UNDERLYINGTYPE + ": "); Write(H5Types.ToJsName(etype, Emitter)); Emitter.Comma = true; } } if (HasEntryPoint) { EnsureComma(); Write(JS.Fields.ENTRY_POINT + ": true"); Emitter.Comma = true; } var ctorBlock = new ConstructorBlock(Emitter, TypeInfo, false); if (TypeInfo.HasRealInstantiable(Emitter) || TypeInfo.ClassType == ClassType.Struct) { ctorBlock.Emit(); new MethodBlock(Emitter, TypeInfo, false).Emit(); } }
protected override void DoEmit() { IAttribute attribute = Attribute; var type = Emitter.GetTypeDefinition(attribute.AttributeType); var argsInfo = new ArgumentsInfo(Emitter, attribute); string inlineCode = Emitter.GetInline(attribute.Constructor); var customCtor = Emitter.Validator.GetCustomConstructor(type) ?? ""; var hasInitializer = attribute.NamedArguments.Count > 0; if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success) { WriteOpenBrace(); WriteSpace(); if (hasInitializer) { WriteObjectInitializer(attribute.NamedArguments, type, attribute); WriteSpace(); } else if (Emitter.Validator.IsObjectLiteral(type)) { WriteObjectInitializer(null, type, attribute); WriteSpace(); } WriteCloseBrace(); } else { if (hasInitializer) { Write(JS.Types.H5.APPLY); WriteOpenParentheses(); } if (inlineCode != null) { new InlineArgumentsBlock(Emitter, argsInfo, inlineCode, attribute.Constructor).Emit(); } else { if (String.IsNullOrEmpty(customCtor)) { WriteNew(); Write(H5Types.ToJsName(attribute.AttributeType, Emitter)); } else { Write(customCtor); } if (!Emitter.Validator.IsExternalType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1)) { WriteDot(); var name = OverloadsCollection.Create(Emitter, attribute.Constructor).GetOverloadName(); Write(name); } WriteOpenParentheses(); WritePositionalList(attribute.PositionalArguments, attribute); WriteCloseParentheses(); } if (hasInitializer) { WriteComma(); BeginBlock(); var inlineInit = WriteObjectInitializer(attribute.NamedArguments, type, attribute); WriteNewLine(); EndBlock(); if (inlineInit.Count > 0) { Write(", function () "); BeginBlock(); foreach (var init in inlineInit) { Write(init); WriteNewLine(); } EndBlock(); } WriteSpace(); WriteCloseParentheses(); } } }
protected virtual void EmitCtorForInstantiableClass() { var baseType = Emitter.GetBaseTypeDefinition(); var typeDef = Emitter.GetTypeDefinition(); var isObjectLiteral = Emitter.Validator.IsObjectLiteral(typeDef); var isPlainMode = Emitter.Validator.GetObjectCreateMode(typeDef) == 0; var ctorWrappers = isObjectLiteral ? new string[0] : EmitInitMembers().ToArray(); if (!TypeInfo.HasRealInstantiable(Emitter) && ctorWrappers.Length == 0 || isObjectLiteral && isPlainMode) { if (ctorHeader) { WriteNewLine(); EndBlock(); } return; } bool forceDefCtor = isObjectLiteral && Emitter.Validator.GetObjectCreateMode(typeDef) == 1 && TypeInfo.Ctors.Count == 0; if (typeDef.IsValueType || forceDefCtor || (TypeInfo.Ctors.Count == 0 && ctorWrappers.Length > 0)) { TypeInfo.Ctors.Add(new ConstructorDeclaration { Modifiers = Modifiers.Public, Body = new BlockStatement() }); } if (!ctorHeader && TypeInfo.Ctors.Count > 0) { EnsureComma(); ctorHeader = true; Write(JS.Fields.CTORS); WriteColon(); BeginBlock(); } Emitter.InConstructor = true; foreach (var ctor in TypeInfo.Ctors) { var oldRules = Emitter.Rules; if (ctor.Body.HasChildren) { if (Emitter.Resolver.ResolveNode(ctor) is MemberResolveResult rr) { Emitter.Rules = Rules.Get(Emitter, rr.Member); } } EnsureComma(); ResetLocals(); var prevMap = BuildLocalsMap(); var prevNamesMap = BuildLocalsNamesMap(); AddLocals(ctor.Parameters, ctor.Body); var ctorName = JS.Funcs.CONSTRUCTOR; if (TypeInfo.Ctors.Count > 1 && ctor.Parameters.Count > 0) { var overloads = OverloadsCollection.Create(Emitter, ctor); ctorName = overloads.GetOverloadName(); } XmlToJsDoc.EmitComment(this, ctor); Write(ctorName); WriteColon(); WriteFunction(); int pos = Emitter.Output.Length; EmitMethodParameters(ctor.Parameters, null, ctor); var ctorParams = Emitter.Output.ToString().Substring(pos); WriteSpace(); BeginBlock(); var len = Emitter.Output.Length; var requireNewLine = false; var noThisInvocation = ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base; IWriterInfo oldWriter = null; if (ctorWrappers.Length > 0 && noThisInvocation) { oldWriter = SaveWriter(); NewWriter(); } ConvertParamsToReferences(ctor.Parameters); if (len != Emitter.Output.Length) { requireNewLine = true; } if (isObjectLiteral) { if (requireNewLine) { WriteNewLine(); } Write("var " + JS.Vars.D_THIS + " = "); var isBaseObjectLiteral = baseType != null && Emitter.Validator.IsObjectLiteral(baseType); if (isBaseObjectLiteral && baseType != null && (!Emitter.Validator.IsExternalType(baseType) || Emitter.Validator.IsH5Class(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { EmitBaseConstructor(ctor, ctorName, true); } else if (isBaseObjectLiteral && baseType != null && ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { EmitExternalBaseCtor(ctor, ref requireNewLine); } else { Write("{ };"); } WriteNewLine(); string name = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, false); if (name.IsEmpty()) { name = H5Types.ToJsName(TypeInfo.Type, Emitter); } Write(JS.Vars.D_THIS + "." + JS.Funcs.GET_TYPE + " = function () { return " + name + "; };"); WriteNewLine(); Write("(function ()"); BeginBlock(); requireNewLine = false; } var beginPosition = Emitter.Output.Length; if (noThisInvocation) { if (requireNewLine) { WriteNewLine(); } if (isObjectLiteral) { var fieldBlock = new FieldBlock(Emitter, TypeInfo, false, false, true); fieldBlock.Emit(); var properties = TypeInfo.InstanceProperties; var names = new List <string>(properties.Keys); foreach (var name in names) { var props = properties[name]; foreach (var prop in props) { if (prop is PropertyDeclaration p) { if (p.Getter.Body.IsNull && p.Setter.Body.IsNull) { continue; } Write(JS.Types.Object.DEFINEPROPERTY); WriteOpenParentheses(); Write("this, "); WriteScript(OverloadsCollection.Create(Emitter, p).GetOverloadName()); WriteComma(); Emitter.Comma = false; BeginBlock(); var memberResult = Emitter.Resolver.ResolveNode(p) as MemberResolveResult; var block = new VisitorPropertyBlock(Emitter, p); block.EmitPropertyMethod(p, p.Getter, ((IProperty)memberResult.Member).Getter, false, true); block.EmitPropertyMethod(p, p.Setter, ((IProperty)memberResult.Member).Setter, true, true); EnsureComma(true); Write(JS.Fields.ENUMERABLE + ": true"); WriteNewLine(); EndBlock(); WriteCloseParentheses(); Write(";"); WriteNewLine(); } } } } else { Write("this." + JS.Funcs.INITIALIZE + "();"); requireNewLine = true; } } if (!isObjectLiteral) { if (baseType != null && (!Emitter.Validator.IsExternalType(baseType) || Emitter.Validator.IsH5Class(baseType)) || (ctor.Initializer != null && ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.This)) { if (requireNewLine) { WriteNewLine(); requireNewLine = false; } EmitBaseConstructor(ctor, ctorName, false); } else if (baseType != null && (ctor.Initializer == null || ctor.Initializer.IsNull || ctor.Initializer.ConstructorInitializerType == ConstructorInitializerType.Base)) { EmitExternalBaseCtor(ctor, ref requireNewLine); } } var script = Emitter.GetScript(ctor); var hasAdditionalIndent = false; if (script == null) { if (ctor.Body.HasChildren) { if (requireNewLine) { WriteNewLine(); } ctor.Body.AcceptChildren(Emitter); if (!Emitter.IsAsync) { hasAdditionalIndent = Emitter.TempVariables.Count > 0; EmitTempVars(beginPosition, true); } } else if (requireNewLine) { WriteNewLine(); } } else { if (requireNewLine) { WriteNewLine(); } WriteLines(script); } if (oldWriter != null) { WrapBody(oldWriter, ctorWrappers, ctorParams); } if (isObjectLiteral) { if (requireNewLine) { WriteNewLine(); } EndBlock(); Write(")." + JS.Funcs.CALL + "(" + JS.Vars.D_THIS + ");"); WriteNewLine(); Write("return " + JS.Vars.D_THIS + ";"); WriteNewLine(); } if (hasAdditionalIndent) { Indent(); } EndBlock(); Emitter.Comma = true; ClearLocalsMap(prevMap); ClearLocalsNamesMap(prevNamesMap); Emitter.Rules = oldRules; } Emitter.InConstructor = false; if (ctorHeader) { WriteNewLine(); EndBlock(); } }
protected virtual void VisitVariableDeclarationStatement() { bool needVar = true; bool needComma = false; bool addSemicolon = !Emitter.IsAsync; var oldSemiColon = Emitter.EnableSemicolon; var asyncExpressionHandling = Emitter.AsyncExpressionHandling; foreach (var variable in VariableDeclarationStatement.Variables) { WriteSourceMapName(variable.Name); var varName = AddLocal(variable.Name, variable, VariableDeclarationStatement.Type); lastVarName = varName; if (variable.Initializer != null && !variable.Initializer.IsNull && variable.Initializer.ToString().Contains(JS.Vars.FIX_ARGUMENT_NAME)) { continue; } if (needVar) { WriteVar(); needVar = false; } bool isReferenceLocal = false; if (Emitter.LocalsMap != null && Emitter.Resolver.ResolveNode(variable) is LocalResolveResult lrr && Emitter.LocalsMap.ContainsKey(lrr.Variable)) { isReferenceLocal = Emitter.LocalsMap[lrr.Variable].EndsWith(".v"); } lastIsReferenceLocal = isReferenceLocal; var hasInitializer = !variable.Initializer.IsNull; if (variable.Initializer.IsNull && !VariableDeclarationStatement.Type.IsVar()) { var typeDef = Emitter.GetTypeDefinition(VariableDeclarationStatement.Type, true); if (typeDef != null && typeDef.IsValueType && !Emitter.Validator.IsExternalType(typeDef)) { hasInitializer = true; } } if ((!Emitter.IsAsync || hasInitializer || isReferenceLocal) && needComma) { if (Emitter.IsAsync) { WriteSemiColon(true); } else { WriteComma(); } } needComma = true; WriteAwaiters(variable.Initializer); if (!Emitter.IsAsync || hasInitializer || isReferenceLocal) { Write(varName); } if (hasInitializer) { addSemicolon = true; Write(" = "); if (isReferenceLocal) { Write("{ v : "); } var oldValue = Emitter.ReplaceAwaiterByVar; Emitter.ReplaceAwaiterByVar = true; if (!variable.Initializer.IsNull) { variable.Initializer.AcceptVisitor(Emitter); } else { var typerr = Emitter.Resolver.ResolveNode(VariableDeclarationStatement.Type).Type; var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, Emitter); bool hadCustomConstructor = false; if (typerr.Kind == ICSharpCode.NRefactory.TypeSystem.TypeKind.Struct) { var type = Emitter.GetTypeDefinition(typerr); var customCtor = (Emitter.Validator.GetCustomConstructor(type) ?? ""); if (!string.IsNullOrEmpty(customCtor)) { hadCustomConstructor = true; Write(string.Concat(customCtor, "()")); } } if (!hadCustomConstructor) { Write(string.Concat("new ", isGeneric ? "(" : "", H5Types.ToJsName(VariableDeclarationStatement.Type, Emitter), isGeneric ? ")" : "", "()")); } } Emitter.ReplaceAwaiterByVar = oldValue; if (isReferenceLocal) { Write(" }"); } } else if (isReferenceLocal) { addSemicolon = true; Write(" = { }"); } } Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (Emitter.EnableSemicolon && !needVar && addSemicolon) { WriteSemiColon(true); } if (oldSemiColon) { Emitter.EnableSemicolon = true; } }
protected virtual void EmitClassHeader() { WriteTopInitMethods(); var typeDef = Emitter.GetTypeDefinition(); string name = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, false); IsGeneric = typeDef.GenericParameters.Count > 0 && !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter); if (name.IsEmpty()) { name = H5Types.ToJsName(TypeInfo.Type, Emitter, asDefinition: true, nomodule: true, ignoreLiteralName: false); } if (typeDef.IsInterface && typeDef.HasGenericParameters) { Write(JS.Types.H5.DEFINE_I); } else { Write(JS.Types.H5.DEFINE); } WriteOpenParentheses(); WriteScript(name); StartPosition = Emitter.Output.Length; Write(", "); if (IsGeneric) { if (TypeInfo.Module != null) { Write(TypeInfo.Module.Name); Write(", "); } WriteFunction(); WriteOpenParentheses(); foreach (var p in typeDef.GenericParameters) { if (typeDef.GenericParameters.Count(gp => gp.FullName == p.FullName) > 1) { throw new EmitterException(TypeInfo.TypeDeclaration, $"Type parameter '{p.FullName}' has the same name as the type parameter from outer type."); } EnsureComma(false); Write(p.Name); Emitter.Comma = true; } Emitter.Comma = false; WriteCloseParentheses(); Write(" { return "); } BeginBlock(); string extend = Emitter.GetTypeHierarchy(); if (extend.IsNotEmpty() && !TypeInfo.IsEnum) { var h5Type = Emitter.H5Types.Get(Emitter.TypeInfo); if (TypeInfo.InstanceMethods.Any(m => m.Value.Any(subm => Emitter.GetEntityName(subm) == JS.Fields.INHERITS)) || TypeInfo.InstanceConfig.Fields.Any(m => m.GetName(Emitter) == JS.Fields.INHERITS)) { Write(JS.Vars.D); } Write(JS.Fields.INHERITS); WriteColon(); if (Helpers.IsTypeArgInSubclass(h5Type.TypeDefinition, h5Type.TypeDefinition, Emitter, false)) { WriteFunction(); WriteOpenCloseParentheses(true); WriteOpenBrace(true); WriteReturn(true); Write(extend); WriteSemiColon(); WriteCloseBrace(true); } else { Write(extend); } Emitter.Comma = true; } WriteKind(); EmitMetadata(); WriteObjectLiteral(); if (TypeInfo.Module != null) { WriteScope(); WriteModule(); } WriteVariance(); }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = Emitter.H5Types.ToType(type); bool isCastAttr; string castCode = GetCastCode(expression, type, method, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = Helpers.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, Emitter)) || IsExternalCast(itype)) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(Emitter); return; } var expressionrr = Emitter.Resolver.ResolveNode(expression); var typerr = Emitter.Resolver.ResolveNode(type); if (expressionrr.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(expressionrr.Type); if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, Emitter.Resolver)) { throw new EmitterException(CastExpression, "Enum underlying type is string and cannot be casted to number"); } } if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum) { var cast_rr = Emitter.Resolver.ResolveNode(CastExpression); if (cast_rr is ConstantResolveResult) { var expectedType = Emitter.Resolver.Resolver.GetExpectedType(CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; WriteCastValue(value, expectedType); return; } else { if (cast_rr is ConversionResolveResult conv_rr && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = Emitter.Resolver.Resolver.GetExpectedType(CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { Write(JS.Types.H5.IS); WriteOpenParentheses(); expression.AcceptVisitor(Emitter); Write(", "); Write(H5Types.ToJsName(itype, Emitter)); Write(")"); return; } if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { Write(JS.Funcs.H5_HASVALUE); WriteOpenParentheses(); } expression.AcceptVisitor(Emitter); if (method == CS.Ops.IS) { Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (IsUserDefinedConversion(this, CastExpression.Expression) || IsUserDefinedConversion(this, CastExpression)) { expression.AcceptVisitor(Emitter); return; } } var conversion = Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(Emitter); return; } bool hasValue = false; if (type is SimpleType simpleType && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = Emitter.Rules.Boxing == BoxingRule.Managed && !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { Write("System.Nullable.getValue("); } var typeDef = itype.Kind == TypeKind.TypeParameter ? null : Emitter.GetTypeDefinition(type, true); if (typeDef != null && method == CS.Ops.IS && itype.Kind != TypeKind.Interface && Emitter.Validator.IsObjectLiteral(typeDef) && Emitter.Validator.GetObjectCreateMode(typeDef) == 0) { throw new EmitterException(type, $"ObjectLiteral type ({itype.FullName}) with Plain mode cannot be used in 'is' operator. Please define cast logic in Cast attribute or use Constructor mode."); } Write(JS.NS.H5); WriteDot(); Write(method); WriteOpenParentheses(); expression.AcceptVisitor(Emitter); if (!hasValue) { WriteComma(); EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { WriteComma(); WriteScript(true); } WriteCloseParentheses(); if (unbox) { Write(")"); } }
protected virtual void EmitStructMethods() { var typeDef = Emitter.GetTypeDefinition(); string structName = H5Types.ToJsName(TypeInfo.Type, Emitter); bool immutable = Emitter.Validator.IsImmutableType(typeDef); if (!immutable) { var mutableFields = TypeInfo.Type.GetFields(f => !f.IsConst, GetMemberOptions.IgnoreInheritedMembers); var autoProps = typeDef.Properties.Where(Helpers.IsAutoProperty); var autoEvents = TypeInfo.Type.GetEvents(null, GetMemberOptions.IgnoreInheritedMembers); immutable = !mutableFields.Any() && !autoProps.Any() && !autoEvents.Any(); } var fields = TypeInfo.InstanceConfig.Fields; var props = TypeInfo.InstanceConfig.Properties.Where(ent => { return(ent.Entity is PropertyDeclaration p && p.Getter != null && p.Getter.Body.IsNull && p.Setter != null && p.Setter.Body.IsNull); }); var list = fields.ToList(); list.AddRange(props); if (list.Count == 0) { EnsureComma(); Write(JS.Funcs.CLONE + ": function (to) { return this; }"); Emitter.Comma = true; return; } if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.GETHASHCODE)) { EnsureComma(); Write(JS.Funcs.GETHASHCODE + ": function () "); BeginBlock(); Write("var h = " + JS.Funcs.H5_ADDHASH + "(["); var nameHashValue = new HashHelper().GetDeterministicHash(TypeInfo.Name); Write(nameHashValue); foreach (var field in list) { string fieldName = field.GetName(Emitter); Write(", this." + fieldName); } Write("]);"); WriteNewLine(); Write("return h;"); WriteNewLine(); EndBlock(); Emitter.Comma = true; } if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.EQUALS)) { EnsureComma(); Write(JS.Funcs.EQUALS + ": function (o) "); BeginBlock(); Write("if (!" + JS.Types.H5.IS + "(o, "); Write(structName); Write(")) "); BeginBlock(); Write("return false;"); WriteNewLine(); EndBlock(); WriteNewLine(); Write("return "); bool and = false; foreach (var field in list) { string fieldName = field.GetName(Emitter); if (and) { Write(" && "); } and = true; Write(JS.Funcs.H5_EQUALS + "(this."); Write(fieldName); Write(", o."); Write(fieldName); Write(")"); } Write(";"); WriteNewLine(); EndBlock(); Emitter.Comma = true; } EnsureComma(); if (immutable) { Write(JS.Funcs.CLONE + ": function (to) { return this; }"); } else { Write(JS.Funcs.CLONE + ": function (to) "); BeginBlock(); Write("var s = to || new "); if (TypeInfo.Type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(TypeInfo.Type, Emitter)) { structName = "(" + structName + ")"; } Write(structName); Write("();"); foreach (var field in list) { WriteNewLine(); string fieldName = field.GetName(Emitter); Write("s."); Write(fieldName); Write(" = "); int insertPosition = Emitter.Output.Length; Write("this."); Write(fieldName); var rr = Emitter.Resolver.ResolveNode(field.Entity) as MemberResolveResult; if (rr == null && field.VarInitializer != null) { rr = Emitter.Resolver.ResolveNode(field.VarInitializer) as MemberResolveResult; } if (rr != null) { Helpers.CheckValueTypeClone(rr, null, this, insertPosition); } Write(";"); } WriteNewLine(); Write("return s;"); WriteNewLine(); EndBlock(); } Emitter.Comma = true; }
protected void VisitObjectCreateExpression() { ObjectCreateExpression objectCreateExpression = ObjectCreateExpression; var resolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression.Type) as TypeResolveResult; if (resolveResult != null && resolveResult.Type.Kind == TypeKind.Enum) { Write("(0)"); return; } bool isTypeParam = resolveResult != null && resolveResult.Type.Kind == TypeKind.TypeParameter; var invocationResolveResult = Emitter.Resolver.ResolveNode(objectCreateExpression) as InvocationResolveResult; var hasInitializer = !objectCreateExpression.Initializer.IsNull && objectCreateExpression.Initializer.Elements.Count > 0; if (isTypeParam && invocationResolveResult != null && invocationResolveResult.Member.Parameters.Count == 0 && !hasInitializer) { Write(JS.Funcs.H5_CREATEINSTANCE); WriteOpenParentheses(); Write(resolveResult.Type.Name); WriteCloseParentheses(); return; } var type = isTypeParam ? null : Emitter.GetTypeDefinition(objectCreateExpression.Type); var isObjectLiteral = type != null && Emitter.Validator.IsObjectLiteral(type); if (type != null && type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate") { bool wrap = false; if (objectCreateExpression.Parent is InvocationExpression parent && parent.Target == objectCreateExpression) { wrap = true; } if (wrap) { WriteOpenParentheses(); } Write("H5.fn.$build(["); objectCreateExpression.Arguments.First().AcceptVisitor(Emitter); Write("])"); if (wrap) { WriteCloseParentheses(); } return; } var argsInfo = new ArgumentsInfo(Emitter, objectCreateExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; string inlineCode = null; if (invocationResolveResult != null) { if (invocationResolveResult.Member.DeclaringType.Kind == TypeKind.Struct && objectCreateExpression.Arguments.Count == 0) { var ctors = invocationResolveResult.Member.DeclaringType.GetConstructors(c => c.Parameters.Count == 1); var defCtor = ctors.FirstOrDefault(c => c.Parameters.First().Type.FullName == "System.Runtime.CompilerServices.DummyTypeUsedToAddAttributeToDefaultValueTypeConstructor"); if (defCtor != null) { inlineCode = Emitter.GetInline(defCtor); } } if (inlineCode == null) { inlineCode = Emitter.GetInline(invocationResolveResult.Member); } } var customCtor = isTypeParam ? "" : (Emitter.Validator.GetCustomConstructor(type) ?? ""); AstNodeCollection <Expression> elements = null; if (hasInitializer) { elements = objectCreateExpression.Initializer.Elements; } var isPlainObjectCtor = Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success; var isPlainMode = type != null && Emitter.Validator.GetObjectCreateMode(type) == 0; if (inlineCode == null && isPlainObjectCtor && isPlainMode) { WriteOpenBrace(); WriteSpace(); var pos = Emitter.Output.Length; WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, false); if (pos < Emitter.Output.Length) { WriteSpace(); } WriteCloseBrace(); } else { string tempVar = null; if (hasInitializer) { tempVar = GetTempVarName(); WriteOpenParentheses(); Write(tempVar); Write(" = "); } if (inlineCode != null) { new InlineArgumentsBlock(Emitter, argsInfo, inlineCode).Emit(); } else { var ctorMember = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member; var expandParams = ctorMember.Attributes.Any(a => a.AttributeType.FullName == "H5.ExpandParamsAttribute"); bool applyCtor = false; if (expandParams) { var ctor_rr = Emitter.Resolver.ResolveNode(paramsArg); if (ctor_rr.Type.Kind == TypeKind.Array && !(paramsArg is ArrayCreateExpression) && objectCreateExpression.Arguments.Last() == paramsArg) { Write(JS.Types.H5.Reflection.APPLYCONSTRUCTOR + "("); applyCtor = true; } } if (String.IsNullOrEmpty(customCtor) || (isObjectLiteral && isPlainObjectCtor)) { if (!applyCtor && !isObjectLiteral) { WriteNew(); } var typerr = Emitter.Resolver.ResolveNode(objectCreateExpression.Type).Type; var td = typerr.GetDefinition(); var isGeneric = typerr.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(typerr, Emitter) || td != null && Validator.IsVirtualTypeStatic(td); if (isGeneric && !applyCtor) { WriteOpenParentheses(); } objectCreateExpression.Type.AcceptVisitor(Emitter); if (isGeneric && !applyCtor) { WriteCloseParentheses(); } } else { Write(customCtor); } if (!isTypeParam && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType || isObjectLiteral ? 0 : 1)) { var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(objectCreateExpression)).Member; if (!Emitter.Validator.IsExternalType(type) || member.Attributes.Any(a => a.AttributeType.FullName == "H5.NameAttribute")) { WriteDot(); var name = OverloadsCollection.Create(Emitter, member).GetOverloadName(); Write(name); } } if (applyCtor) { Write(", "); } else { WriteOpenParentheses(); } new ExpressionListBlock(Emitter, argsExpressions, paramsArg, objectCreateExpression, -1).Emit(); WriteCloseParentheses(); } if (hasInitializer) { if (isObjectLiteral && isPlainMode) { WriteObjectInitializer(objectCreateExpression.Initializer.Elements, type, invocationResolveResult, true); } else { foreach (Expression item in elements) { WriteInitializerExpression(item, tempVar); } } WriteComma(); Write(tempVar); WriteCloseParentheses(); RemoveTempVar(tempVar); } } //Helpers.CheckValueTypeClone(invocationResolveResult, this.ObjectCreateExpression, this, pos); }