private void EmitExternalBaseCtor(ConstructorDeclaration ctor, ref bool requireNewLine) { IMember member = null; var hasInitializer = ctor.Initializer != null && !ctor.Initializer.IsNull; var baseType = Emitter.GetBaseTypeDefinition(); if (hasInitializer) { member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; } if (member != null) { var inlineCode = Emitter.GetInline(member); if (!string.IsNullOrEmpty(inlineCode)) { if (requireNewLine) { WriteNewLine(); requireNewLine = false; } Write(JS.Types.H5.APPLY); WriteOpenParentheses(); Write("this, "); var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); new InlineArgumentsBlock(Emitter, argsInfo, inlineCode).Emit(); WriteCloseParentheses(); WriteSemiColon(); WriteNewLine(); return; } } if (hasInitializer || (baseType.FullName != "System.Object" && baseType.FullName != "System.ValueType" && baseType.FullName != "System.Enum" && !baseType.CustomAttributes.Any(a => a.AttributeType.FullName == "H5.NonScriptableAttribute") && !baseType.IsInterface)) { if (requireNewLine) { WriteNewLine(); requireNewLine = false; } string name = null; if (TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } Write(name); WriteCall(); int openPos = Emitter.Output.Length; WriteOpenParentheses(); Write("this"); if (hasInitializer && ctor.Initializer.Arguments.Count > 0) { Write(", "); var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } WriteCloseParentheses(); WriteSemiColon(); WriteNewLine(); } }
protected virtual void EmitBaseConstructor(ConstructorDeclaration ctor, string ctorName, bool isObjectLiteral) { var initializer = ctor.Initializer != null && !ctor.Initializer.IsNull ? ctor.Initializer : new ConstructorInitializer() { ConstructorInitializerType = ConstructorInitializerType.Base }; bool appendScope = false; bool isBaseObjectLiteral = false; if (initializer.ConstructorInitializerType == ConstructorInitializerType.Base) { var baseType = Emitter.GetBaseTypeDefinition(); //var baseName = JS.Funcs.CONSTRUCTOR; string baseName = null; isBaseObjectLiteral = Emitter.Validator.IsObjectLiteral(baseType); if (ctor.Initializer != null && !ctor.Initializer.IsNull) { var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; var overloads = OverloadsCollection.Create(Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } } string name = null; if (TypeInfo.GetBaseTypes(Emitter).Any()) { name = H5Types.ToJsName(TypeInfo.GetBaseClass(Emitter), Emitter); } else { name = H5Types.ToJsName(baseType, Emitter); } if (!isObjectLiteral && isBaseObjectLiteral) { Write(JS.Types.H5.COPY_PROPERTIES); WriteOpenParentheses(); Write("this, "); } Write(name, "."); if (baseName == null) { var baseIType = Emitter.H5Types.Get(baseType).Type; var baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 0); if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.All(p => p.IsOptional)); } if (baseCtor == null) { baseCtor = baseIType.GetConstructors().SingleOrDefault(c => c.Parameters.Count == 1 && c.Parameters.First().IsParams); } if (baseCtor != null) { baseName = OverloadsCollection.Create(Emitter, baseCtor).GetOverloadName(); } else { baseName = JS.Funcs.CONSTRUCTOR; } } Write(baseName); if (!isObjectLiteral) { WriteCall(); appendScope = true; } } else { // this.WriteThis(); string name = H5Types.ToJsName(TypeInfo.Type, Emitter); Write(name); WriteDot(); var baseName = JS.Funcs.CONSTRUCTOR; var member = ((InvocationResolveResult)Emitter.Resolver.ResolveNode(ctor.Initializer)).Member; var overloads = OverloadsCollection.Create(Emitter, member); if (overloads.HasOverloads) { baseName = overloads.GetOverloadName(); } Write(baseName); if (!isObjectLiteral) { WriteCall(); appendScope = true; } } int openPos = Emitter.Output.Length; WriteOpenParentheses(); if (appendScope) { WriteThis(); if (initializer.Arguments.Count > 0) { WriteComma(); } } if (initializer.Arguments.Count > 0) { var argsInfo = new ArgumentsInfo(Emitter, ctor.Initializer); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; new ExpressionListBlock(Emitter, argsExpressions, paramsArg, ctor.Initializer, openPos).Emit(); } if (!isObjectLiteral && isBaseObjectLiteral) { WriteCloseParentheses(); } WriteCloseParentheses(); WriteSemiColon(); if (!isObjectLiteral) { WriteNewLine(); } }
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(); } }