public Emitter(IDictionary <string, TypeDefinition> typeDefinitions, H5Types h5Types, List <ITypeInfo> types, IValidator validator, IMemberResolver resolver, Dictionary <string, ITypeInfo> typeInfoDefinitions, CancellationToken cancellationToken) { Resolver = resolver; TypeDefinitions = typeDefinitions; TypeInfoDefinitions = typeInfoDefinitions; Types = types; H5Types = h5Types; CancellationToken = cancellationToken; H5Types.InitItems(this); using (new Measure(Logger, "Sorting types by name", logOnlyDuration: true)) { Types.Sort(CompareTypeInfosByName); } SortTypesByInheritance(); Validator = validator; AssignmentType = ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Any; UnaryOperatorType = ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Any; JsDoc = new JsDoc(); AnonymousTypes = new Dictionary <AnonymousType, IAnonymousTypeConfig>(); AutoStartupMethods = new List <string>(); Cache = new EmitterCache(); AssemblyNameRuleCache = new Dictionary <IAssembly, NameRule[]>(); ClassNameRuleCache = new Dictionary <ITypeDefinition, NameRule[]>(); AssemblyCompilerRuleCache = new Dictionary <IAssembly, CompilerRule[]>(); ClassCompilerRuleCache = new Dictionary <ITypeDefinition, CompilerRule[]>(); }
private void WriteEvent(TypeConfigItem ev, string name, bool adder) { XmlToJsDoc.EmitComment(this, ev.Entity, adder); Write(name); WriteOpenParentheses(); Write("value"); WriteColon(); string typeName = H5Types.ToTypeScriptName(ev.Entity.ReturnType, Emitter); Write(typeName); var resolveResult = Emitter.Resolver.ResolveNode(ev.Entity.ReturnType); if (resolveResult != null && (resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT))) { Write(" | null"); } WriteCloseParentheses(); WriteColon(); Write("void"); WriteSemiColon(); WriteNewLine(); }
protected void WriteSimpleTarget(ResolveResult resolveResult) { if (!(resolveResult is MemberResolveResult member) || !member.Member.IsStatic) { MemberReferenceExpression.Target.AcceptVisitor(Emitter); return; } var imethod = member.Member as IMethod; var imember = member.Member; if ((imethod != null && imethod.IsExtensionMethod) || imember == null) { MemberReferenceExpression.Target.AcceptVisitor(Emitter); return; } var target = H5Types.ToJsName(member.Member.DeclaringType, Emitter, ignoreLiteralName: false); NoTarget = string.IsNullOrWhiteSpace(target); if (member.Member.IsStatic && target != CS.NS.H5 && !Validator.IsTypeFromH5ButNotFromH5Core(target) && MemberReferenceExpression.Target.ToString().StartsWith(CS.NS.GLOBAL)) { Write(JS.Types.H5.Global.DOTNAME); } Write(target); }
private void WriteAccessor(PropertyDeclaration p, MemberResolveResult memberResult, bool ignoreInterface) { string name = Helpers.GetPropertyRef(memberResult.Member, Emitter, false, false, ignoreInterface); Write(name); var property_rr = Emitter.Resolver.ResolveNode(p); if (property_rr is MemberResolveResult mrr && mrr.Member.Attributes.Any(a => a.AttributeType.FullName == "H5.OptionalAttribute")) { Write("?"); } WriteColon(); name = H5Types.ToTypeScriptName(p.ReturnType, Emitter); Write(name); var resolveResult = Emitter.Resolver.ResolveNode(p.ReturnType); if (resolveResult != null && (resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT))) { Write(" | null"); } WriteSemiColon(); WriteNewLine(); }
private void WriteCustomAwaiter(AstNode node, InvocationResolveResult awaiterMethod) { var method = awaiterMethod.Member; var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { var argsInfo = new ArgumentsInfo(Emitter, node as Expression, awaiterMethod); new InlineArgumentsBlock(Emitter, argsInfo, inline).Emit(); } else { if (method.IsStatic) { Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); WriteOpenParentheses(); new ExpressionListBlock(Emitter, new Expression[] { (Expression)node }, null, null, 0).Emit(); WriteCloseParentheses(); } else { node.AcceptVisitor(Emitter); WriteDot(); var name = OverloadsCollection.Create(Emitter, method).GetOverloadName(); Write(name); WriteOpenParentheses(); WriteCloseParentheses(); } } }
protected virtual void EmitMethodParameters(IEnumerable <ParameterDeclaration> declarations, AstNode context) { WriteOpenParentheses(); bool needComma = false; foreach (var p in declarations) { var name = Emitter.GetParameterName(p); if (needComma) { WriteComma(); } needComma = true; Write(name); WriteColon(); name = H5Types.ToTypeScriptName(p.Type, Emitter); Write(name); var resolveResult = Emitter.Resolver.ResolveNode(p.Type); if (resolveResult != null && (resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT))) { Write(" | null"); } } WriteCloseParentheses(); }
protected virtual void EmitMethodParameters(IEnumerable <ParameterDeclaration> declarations, IEnumerable <TypeParameterDeclaration> typeParamsdeclarations, AstNode context, bool skipClose) { WriteOpenParentheses(); bool needComma = false; foreach (var p in declarations) { var name = Emitter.GetParameterName(p); if (needComma) { WriteComma(); } needComma = true; Write(name); WriteColon(); name = H5Types.ToTypeScriptName(p.Type, Emitter); Write(name); } if (!skipClose) { WriteCloseParentheses(); } }
public static string DefaultValue(ResolveResult resolveResult, IEmitter emitter, AstType astType = null) { if ((!resolveResult.IsError && resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value) || resolveResult.Type.Kind == TypeKind.Dynamic || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT)) { return("null"); } if (resolveResult.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(resolveResult.Type); var isString = enumMode >= 3 && enumMode <= 6; return(isString ? "null" : "0"); } if (resolveResult.Type.Kind == TypeKind.Struct) { var type = emitter.GetTypeDefinition(resolveResult.Type); var customCtor = (emitter.Validator.GetCustomConstructor(type) ?? ""); if (!string.IsNullOrEmpty(customCtor)) { return(customCtor + "()"); } } return(JS.Funcs.H5_GETDEFAULTVALUE + "(" + (astType != null ? H5Types.ToJsName(astType, emitter) : H5Types.ToJsName(resolveResult.Type, emitter)) + ")"); }
private void WriteAccessor(IndexerDeclaration indexerDeclaration, bool setter, bool ignoreInterface) { XmlToJsDoc.EmitComment(this, IndexerDeclaration, !setter); string name = Helpers.GetPropertyRef(IndexerDeclaration, Emitter, setter, false, ignoreInterface); Write(name); EmitMethodParameters(indexerDeclaration.Parameters, null, indexerDeclaration, setter); if (setter) { Write(", value"); WriteColon(); name = H5Types.ToTypeScriptName(indexerDeclaration.ReturnType, Emitter); Write(name); WriteCloseParentheses(); WriteColon(); Write("void"); } else { WriteColon(); name = H5Types.ToTypeScriptName(indexerDeclaration.ReturnType, Emitter); Write(name); } WriteSemiColon(); WriteNewLine(); }
protected void EmitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { XmlToJsDoc.EmitComment(this, operatorDeclaration); var overloads = OverloadsCollection.Create(Emitter, operatorDeclaration); if (overloads.HasOverloads) { string name = overloads.GetOverloadName(); Write(name); } else { Write(Emitter.GetEntityName(operatorDeclaration)); } EmitMethodParameters(operatorDeclaration.Parameters, operatorDeclaration); WriteColon(); var retType = H5Types.ToTypeScriptName(operatorDeclaration.ReturnType, Emitter); Write(retType); WriteSemiColon(); WriteNewLine(); }
public IList <ITypeInfo> GetParents(IType type, List <ITypeInfo> list = null) { IList <ITypeInfo> result; if (cacheParents.TryGetValue(type, out result)) { list?.AddRange(result); return(result); } bool endPoint = list == null; if (endPoint) { activeTypes = new Stack <IType>(); list = new List <ITypeInfo>(); } var typeDef = type.GetDefinition() ?? type; if (activeTypes.Contains(typeDef)) { return(list); } activeTypes.Push(typeDef); var types = type.GetAllBaseTypes(); var thisTypelist = new List <ITypeInfo>(); foreach (var t in types) { var bType = H5Types.Get(t, true); if (bType?.TypeInfo != null && !bType.Type.Equals(typeDef)) { thisTypelist.Add(bType.TypeInfo); } if (t.TypeArguments.Count > 0) { foreach (var typeArgument in t.TypeArguments) { bType = H5Types.Get(typeArgument, true); if (bType?.TypeInfo != null && !bType.Type.Equals(typeDef)) { thisTypelist.Add(bType.TypeInfo); } GetParents(typeArgument, thisTypelist); } } } list.AddRange(thisTypelist); activeTypes.Pop(); list = list.Distinct().ToList(); cacheParents[type] = list; return(list); }
public virtual TypeDefinition GetTypeDefinition(AstType reference, bool safe = false) { var resolveResult = Resolver.ResolveNode(reference) as TypeResolveResult; var type = H5Types.Get(resolveResult.Type, safe); return(type?.TypeDefinition); }
private static string GetTypeName(IType type, IEmitter emitter) { /*var typeParam = type as ITypeParameter; * if (typeParam != null && typeParam.OwnerType == SymbolKind.Method) * { * return "Object"; * }*/ return(H5Types.ToJsName(type, emitter)); }
public virtual TypeDefinition GetBaseTypeDefinition(TypeDefinition type) { var reference = type.BaseType; if (reference == null) { return(null); } return(H5Types.Get(reference).TypeDefinition); }
protected virtual StringBuilder GetOutputForType(ITypeInfo typeInfo) { var info = H5Types.GetNamespaceFilename(typeInfo, Emitter); var ns = info.Item1; var fileName = info.Item2; var module = info.Item3; StringBuilder output = null; OutputKey key = new OutputKey(fileName, module, ns); if (this.ns != null && (this.ns != ns || outputKey != null && !outputKey.Equals(key))) { EndBlock(); WriteNewLine(); } this.ns = ns; outputKey = key; if (Outputs.ContainsKey(key)) { output = Outputs[key]; } else { if (Emitter.Output != null) { InsertDependencies(Emitter.Output); } output = new StringBuilder(); Emitter.Output = output; if (ns != null) { if (module == null || module.Type == ModuleType.UMD) { output.Append("declare "); } output.Append("namespace " + ns + " "); BeginBlock(); } Outputs.Add(key, output); Emitter.CurrentDependencies = new List <IPluginDependency>(); } return(output); }
protected virtual IEnumerable <string> GetAfterDefineMethods() { return(GetDefineMethods(InitPosition.After, (method, rrMethod) => { Emitter.InitPosition = InitPosition.After; var callback = JS.Types.H5.INIT + "(function () { " + H5Types.ToJsName(rrMethod.DeclaringTypeDefinition, Emitter) + "." + Emitter.GetEntityName(method) + "(); });"; Emitter.InitPosition = null; return callback; })); }
protected override void DoEmit() { var typeDef = Emitter.GetTypeDefinition(); string name = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, true, false); if (name.IsEmpty()) { name = H5Types.ToTypeScriptName(TypeInfo.Type, Emitter, false, true); } Write("enum "); Write(name); WriteSpace(); BeginBlock(); if (TypeInfo.StaticConfig.Fields.Count > 0) { var lastField = TypeInfo.StaticConfig.Fields.Last(); foreach (var field in TypeInfo.StaticConfig.Fields) { Write(GetEnumItemName(Emitter, field)); var initializer = field.Initializer; if (initializer != null && initializer is PrimitiveExpression) { Write(" = "); if (Helpers.IsStringNameEnum(TypeInfo.Type)) { WriteScript(((PrimitiveExpression)initializer).Value); } else { Write(((PrimitiveExpression)initializer).Value); } } if (field != lastField) { Write(","); } WriteNewLine(); } } EndBlock(); }
protected virtual void EmitStructMethods() { var typeDef = Emitter.GetTypeDefinition(); string structName = H5Types.ToTypeScriptName(TypeInfo.Type, Emitter); if (TypeInfo.InstanceConfig.Fields.Count == 0) { Write(JS.Funcs.CLONE + "(to"); WriteColon(); Write(structName); WriteCloseParentheses(); WriteColon(); Write(structName); WriteSemiColon(); WriteNewLine(); return; } if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.GETHASHCODE)) { Write(JS.Funcs.GETHASHCODE + "()"); WriteColon(); Write("number"); WriteSemiColon(); WriteNewLine(); } if (!TypeInfo.InstanceMethods.ContainsKey(CS.Methods.EQUALS)) { Write(JS.Funcs.EQUALS + "(o"); WriteColon(); Write(structName); WriteCloseParentheses(); WriteColon(); Write("boolean"); WriteSemiColon(); WriteNewLine(); } Write(JS.Funcs.CLONE + "(to"); WriteColon(); Write(structName); WriteCloseParentheses(); WriteColon(); Write(structName); WriteSemiColon(); WriteNewLine(); }
public static string GetStructDefaultValue(IType type, IEmitter emitter) { if (type.IsKnownType(KnownTypeCode.DateTime)) { return(string.Format("{0}()", JS.Types.System.DateTime.GET_DEFAULT_VALUE)); } var isGeneric = type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(type, emitter); if (emitter.Validator.IsObjectLiteral(emitter.GetTypeDefinition(type))) { return("{}"); } return(string.Concat("new ", isGeneric ? "(" : "", H5Types.ToJsName(type, emitter), isGeneric ? ")" : "", "()")); }
public static string DefaultValue(ResolveResult resolveResult, IEmitter emitter, AstType astType = null) { if ((!resolveResult.IsError && resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value) || resolveResult.Type.Kind == TypeKind.Dynamic || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT)) { return("null"); } if (resolveResult.Type.Kind == TypeKind.Enum) { var enumMode = Helpers.EnumEmitMode(resolveResult.Type); var isString = enumMode >= 3 && enumMode <= 6; return(isString ? "null" : "0"); } return(JS.Funcs.H5_GETDEFAULTVALUE + "(" + (astType != null ? H5Types.ToJsName(astType, emitter) : H5Types.ToJsName(resolveResult.Type, emitter)) + ")"); }
protected virtual ITypeInfo EnsureTypeInfo(TypeDefinition type, ITranslator translator) { string key = H5Types.GetTypeDefinitionKey(type); ITypeInfo typeInfo = null; if (translator.TypeInfoDefinitions.ContainsKey(key)) { typeInfo = translator.TypeInfoDefinitions[key]; } else { typeInfo = new TypeInfo(); translator.TypeInfoDefinitions[key] = typeInfo; } return(typeInfo); }
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 WriteNestedDefs() { if (NestedTypes != null) { foreach (var nestedType in NestedTypes) { var typeDef = Emitter.GetTypeDefinition(nestedType.Type); if (typeDef.IsInterface || Emitter.Validator.IsObjectLiteral(typeDef)) { continue; } string customName = Emitter.Validator.GetCustomTypeName(typeDef, Emitter, true); string defName = customName; if (defName.IsEmpty()) { defName = H5Types.ToTypeScriptName(nestedType.Type, Emitter, true); Write(H5Types.ToTypeScriptName(nestedType.Type, Emitter, true, true)); } else { Write(defName); } if (typeDef.IsEnum) { var parentTypeDef = Emitter.GetTypeDefinition(); string parentName = Emitter.Validator.GetCustomTypeName(parentTypeDef, Emitter, false, false); if (parentName.IsEmpty()) { parentName = TypeInfo.Type.Name; } defName = parentName + "." + H5Types.ToTypeScriptName(nestedType.Type, Emitter, false, true); } WriteColon(); Write(defName + "Func"); WriteSemiColon(); WriteNewLine(); } } }
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 bool ResolveOperator(UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult orr) { if (orr != null && orr.UserDefinedOperatorMethod != null) { var method = orr.UserDefinedOperatorMethod; var inline = Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(Emitter, new ArgumentsInfo(Emitter, unaryOperatorExpression, orr, method), inline).Emit(); return(true); } else { if (orr.IsLiftedOperator) { Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT + "("); } Write(H5Types.ToJsName(method.DeclaringType, Emitter)); WriteDot(); Write(OverloadsCollection.Create(Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { WriteComma(); } else { WriteOpenParentheses(); } new ExpressionListBlock(Emitter, new Expression[] { unaryOperatorExpression.Expression }, null, null, 0).Emit(); WriteCloseParentheses(); return(true); } } return(false); }
public virtual string GetTypeHierarchy() { StringBuilder sb = new StringBuilder(); sb.Append("["); var list = new List <string>(); foreach (var t in TypeInfo.GetBaseTypes(this)) { var name = H5Types.ToJsName(t, this); list.Add(name); } if (list.Count > 0 && list[0] == JS.Types.System.Object.NAME) { list.RemoveAt(0); } if (list.Count == 0) { return(""); } bool needComma = false; foreach (var item in list) { if (needComma) { sb.Append(","); } needComma = true; sb.Append(item); } sb.Append("]"); return(sb.ToString()); }
private void WriteFieldDeclaration(TypeConfigItem field, VariableInitializer variableInitializer) { XmlToJsDoc.EmitComment(this, field.Entity, null, variableInitializer); if (TypeInfo.IsEnum) { Write(EnumBlock.GetEnumItemName(Emitter, field)); } else { Write(field.GetName(Emitter)); } if (field.VarInitializer != null) { var field_rr = Emitter.Resolver.ResolveNode(field.VarInitializer); if (field_rr is MemberResolveResult mrr && mrr.Member.Attributes.Any(a => a.AttributeType.FullName == "H5.OptionalAttribute")) { Write("?"); } } WriteColon(); string typeName = TypeInfo.IsEnum ? (Helpers.IsStringNameEnum(TypeInfo.Type) ? "string" : "number") : H5Types.ToTypeScriptName(field.Entity.ReturnType, Emitter); Write(typeName); if (!TypeInfo.IsEnum) { var resolveResult = Emitter.Resolver.ResolveNode(field.Entity.ReturnType); if (resolveResult != null && (resolveResult.Type.IsReferenceType.HasValue && resolveResult.Type.IsReferenceType.Value || resolveResult.Type.IsKnownType(KnownTypeCode.NullableOfT))) { Write(" | null"); } } WriteSemiColon(); WriteNewLine(); }
protected virtual void EmitCastType(AstType astType) { var resolveResult = Emitter.Resolver.ResolveNode(astType); if (NullableType.IsNullable(resolveResult.Type)) { Write(H5Types.ToJsName(NullableType.GetUnderlyingType(resolveResult.Type), Emitter)); } else if (resolveResult.Type.Kind == TypeKind.Delegate) { Write(JS.Types.FUNCTION); } /*else if (resolveResult.Type.Kind == TypeKind.Array) * { * this.EmitArray(resolveResult.Type); * }*/ else { astType.AcceptVisitor(Emitter); } }
protected virtual void EmitExpressionList(IEnumerable <AstType> types) { bool needComma = false; foreach (var type in types) { EnsureComma(false); Emitter.Translator.EmitNode = type; if (needComma) { WriteComma(); } needComma = true; Write(H5Types.ToJsName(type, Emitter)); } if (needComma) { Emitter.Comma = true; } }
protected virtual void EmitPropertyMethod(CustomEventDeclaration customEventDeclaration, Accessor accessor, bool remover) { if (!accessor.IsNull && Emitter.GetInline(accessor) == null) { XmlToJsDoc.EmitComment(this, customEventDeclaration); var memberResult = Emitter.Resolver.ResolveNode(customEventDeclaration) as MemberResolveResult; var ignoreInterface = memberResult.Member.DeclaringType.Kind == TypeKind.Interface && memberResult.Member.DeclaringType.TypeParameterCount > 0; Write(Helpers.GetEventRef(customEventDeclaration, Emitter, remover, false, ignoreInterface)); WriteOpenParentheses(); Write("value"); WriteColon(); var retType = H5Types.ToTypeScriptName(customEventDeclaration.ReturnType, Emitter); Write(retType); WriteCloseParentheses(); WriteColon(); Write("void"); WriteSemiColon(); WriteNewLine(); } }