1 /* This file is part of the 'hgen' project. 2 * 3 * Copyright (c) 2014-2022 4 * Economic Modeling Specialists, Intl., 5 * the D Community. 6 * 7 * Main contributors: 8 * Ferdinand Majerech 9 * Ilya Yaroshenko 10 * Basile Burg 11 * Eugene Stulin 12 * 13 * Distributed under the Boost Software License, Version 1.0. 14 * 15 * You should have received a copy of the Boost Software License 16 * along with this program. If not, see <http://www.boost.org/LICENSE_1_0.txt>. 17 * This file is offered as-is, without any warranty. 18 */ 19 20 module formatter; 21 22 import dparse.ast; 23 import dparse.lexer; 24 import dparse.formatter; 25 import std.stdio; 26 27 28 /******************************************************************************* 29 * Modified D formatter for Harbored. 30 * 31 * Currently the only modification is that multi-parameter parameter lists 32 * are split into multiple lines. 33 */ 34 class HarboredFormatter(Sink) : Formatter!Sink { 35 /// Nesting level for nested parameter lists (see format(const Parameters)). 36 private uint level; 37 38 /// Function to process types with for cross-referencing. 39 private string delegate(string) @safe nothrow crossReference; 40 41 /** 42 * Params: 43 * 44 * sink = the output range that the formatted source code 45 * is placed in 46 * processCode = Function to process types with for cross-referencing. 47 * useTabs = if true, tabs are used for indent levels instead of spaces 48 * style = the brace style 49 * indentWidth = the number of spaces used for indentation 50 * if useTabs is false 51 */ 52 this(Sink sink, 53 string delegate(string) @safe nothrow crossReference, 54 bool useTabs = false, 55 IndentStyle style = IndentStyle.otbs, 56 uint indentWidth = 4 57 ) { 58 this.crossReference = crossReference; 59 super(sink, useTabs, style, indentWidth); 60 } 61 62 alias format = Formatter!Sink.format; 63 64 /** A modified version 65 * of dparse.formatter.Formatter.format(const Parameters) 66 */ 67 override void format(const Parameters parameters) { 68 debug(verbose) writeln("Parameters (HarboredFormatter)"); 69 70 // No need to break the list into multiple lines for a single argument 71 // TODO ability to set this in "doxyfile" 72 const maxParamsForSingleLineParamList = 1; 73 if (parameters.parameters.length <= maxParamsForSingleLineParamList) { 74 super.format(parameters); 75 return; 76 } 77 level++; 78 scope(exit) level--; 79 put("("); 80 bool moreThanThreeArgs = parameters.parameters.length > 3; 81 auto interArgSep = moreThanThreeArgs ? "\n" : ""; 82 foreach (count, param; parameters.parameters) { 83 if (count) { 84 put(", "); 85 } 86 put(interArgSep); 87 if (moreThanThreeArgs) { 88 foreach(i; 0 .. level) { 89 put(" "); 90 } 91 } 92 format(param); 93 } 94 if (parameters.hasVarargs) { 95 if (parameters.parameters.length) { 96 put(", "); 97 } 98 put(interArgSep); 99 if (moreThanThreeArgs) { 100 foreach(i; 0 .. level) { 101 put(" "); 102 } 103 } 104 put("..."); 105 } 106 if (level > 1) { 107 put("\n"); 108 foreach(i; 0..level) { 109 put(" "); 110 } 111 } 112 put(interArgSep); 113 put(")"); 114 } 115 116 // Overridden for builtin type referencing. 117 override void format(const Type2 type2) { 118 debug(verbose) writeln("Type2 (HarboredFormatter)"); 119 120 /** 121 IdType builtinType; 122 Symbol symbol; 123 TypeofExpression typeofExpression; 124 IdentifierOrTemplateChain identifierOrTemplateChain; 125 IdType typeConstructor; 126 Type type; 127 **/ 128 129 if (type2.typeIdentifierPart !is null) { 130 format(type2.typeIdentifierPart); 131 } else if (type2.typeofExpression !is null) { 132 format(type2.typeofExpression); 133 if (type2.typeIdentifierPart) { 134 put("."); 135 format(type2.typeIdentifierPart); 136 } 137 return; 138 } else if (type2.typeConstructor != tok!"") { 139 put(tokenRep(type2.typeConstructor)); 140 put("("); 141 format(type2.type); 142 put(")"); 143 } else { 144 // Link to language reference for builtin types. 145 put(`<a href="http://dlang.org/type.html#basic-data-types">`); 146 put(tokenRep(type2.builtinType)); 147 put("</a>"); 148 } 149 } 150 151 // Overridden for cross-referencing. 152 override void format(const Token token) { 153 debug(verbose) writeln("Token (HarboredFormatter) ", tokenRep(token)); 154 put(crossReference(tokenRep(token))); 155 } 156 157 } 158