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