1 //          Copyright Brian Schott (Hackerpilot) 2012.
2 // Distributed under the Boost Software License, Version 1.0.
3 //    (See accompanying file LICENSE_1_0.txt or copy at
4 //          http://www.boost.org/LICENSE_1_0.txt)
5 
6 module dscanner.outliner;
7 
8 import dparse.lexer;
9 import dparse.ast;
10 import dparse.formatter;
11 import std.stdio;
12 import std.string;
13 import std.array;
14 import std.conv;
15 
16 class Outliner : ASTVisitor
17 {
18 	alias visit = ASTVisitor.visit;
19 
20 	this(File output)
21 	{
22 		this.output = output;
23 	}
24 
25 	override void visit(const ClassDeclaration classDec)
26 	{
27 		printIndentation();
28 		output.writeln("class ", classDec.name.text, " : ", classDec.name.line);
29 		indent();
30 		classDec.accept(this);
31 		outdent();
32 		finish();
33 	}
34 
35 	override void visit(const EnumDeclaration enumDec)
36 	{
37 		printIndentation();
38 		output.writeln("enum ", enumDec.name.text, " : ", enumDec.name.line);
39 		indent();
40 		enumDec.accept(this);
41 		outdent();
42 		finish();
43 	}
44 
45 	override void visit(const AnonymousEnumMember enumMem)
46 	{
47 		printIndentation();
48 		if (enumMem.type !is null)
49 		{
50 			auto app = appender!(char[])();
51 			auto f = new Formatter!(typeof(app))(app);
52 			f.format(enumMem.type);
53 			output.writeln("enum ", app.data, " ", enumMem.name.text, " : ", enumMem.name.line);
54 		}
55 		else
56 			output.writeln("enum ", enumMem.name.text, " : ", enumMem.name.line);
57 		finish();
58 	}
59 
60 	override void visit(const EnumMember enumMem)
61 	{
62 		printIndentation();
63 		output.writeln(enumMem.name.text, " : ", enumMem.name.line);
64 		finish();
65 	}
66 
67 	override void visit(const FunctionDeclaration functionDec)
68 	{
69 		printIndentation();
70 		if (functionDec.hasAuto)
71 			output.write("auto ");
72 		if (functionDec.hasRef)
73 			output.write("ref ");
74 		auto app = appender!(char[])();
75 		auto f = new Formatter!(typeof(app))(app);
76 		if (functionDec.returnType !is null)
77 			f.format(functionDec.returnType);
78 		app.put(" ");
79 		app.put(functionDec.name.text);
80 		f.format(functionDec.parameters);
81 		app.put(" : ");
82 		app.put(to!string(functionDec.name.line));
83 		output.writeln(app.data);
84 		finish();
85 	}
86 
87 	override void visit(const InterfaceDeclaration interfaceDec)
88 	{
89 		printIndentation();
90 		output.writeln("interface ", interfaceDec.name.text, " : ", interfaceDec.name.line);
91 		indent();
92 		interfaceDec.accept(this);
93 		outdent();
94 		finish();
95 	}
96 
97 	override void visit(const StructDeclaration structDec)
98 	{
99 		printIndentation();
100 		output.writeln("struct ", structDec.name.text, " : ", structDec.name.line);
101 		indent();
102 		structDec.accept(this);
103 		outdent();
104 		finish();
105 	}
106 
107 	override void visit(const TemplateDeclaration templateDeclaration)
108 	{
109 		printIndentation();
110 		output.writeln("template ", templateDeclaration.name.text, " : ",
111 				templateDeclaration.name.line);
112 		indent();
113 		templateDeclaration.accept(this);
114 		outdent();
115 		finish();
116 	}
117 
118 	//dfmt off
119 	override void visit(const StaticConstructor s) {}
120 	override void visit(const StaticDestructor s) {}
121 	override void visit(const SharedStaticConstructor s) {}
122 	override void visit(const SharedStaticDestructor s) {}
123 	override void visit(const Constructor c) {}
124 	override void visit(const Unittest u) {}
125 	// dfmt on
126 
127 	override void visit(const UnionDeclaration unionDeclaration)
128 	{
129 		printIndentation();
130 		output.writeln("union ", unionDeclaration.name.text, " : ", unionDeclaration.name.line);
131 		indent();
132 		unionDeclaration.accept(this);
133 		outdent();
134 		finish();
135 	}
136 
137 	override void visit(const VariableDeclaration variableDeclaration)
138 	{
139 		foreach (const Declarator d; variableDeclaration.declarators)
140 		{
141 			printIndentation();
142 			auto app = appender!(char[])();
143 			if (variableDeclaration.type !is null)
144 			{
145 				auto f = new Formatter!(typeof(app))(app);
146 				f.format(variableDeclaration.type);
147 			}
148 			output.writeln(app.data, " ", d.name.text, " : ", d.name.line);
149 		}
150 		finish();
151 	}
152 
153 private:
154 
155 	void finish()
156 	{
157 		if (indentLevel == 0)
158 			output.writeln();
159 	}
160 
161 	void printIndentation()
162 	{
163 		foreach (i; 0 .. indentLevel)
164 			output.write("    ");
165 	}
166 
167 	void indent()
168 	{
169 		indentLevel++;
170 	}
171 
172 	void outdent()
173 	{
174 		indentLevel--;
175 	}
176 
177 	int indentLevel;
178 
179 	File output;
180 }