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