1 /**
2 	Merges eponymous templates to a single definition with template arguments.
3 
4 	Copyright: © 2012-2015 RejectedSoftware e.K.
5 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
6 	Authors: Sönke Ludwig
7 */
8 module ddox.processors.eptemplates;
9 
10 import ddox.api;
11 import ddox.entities;
12 
13 import std.algorithm;
14 
15 
16 void mergeEponymousTemplates(Package root)
17 {
18 	void processDecls(ref Declaration[] decls)
19 	{
20 		Declaration[] new_decls;
21 		foreach (d; decls) {
22 			if (auto templ = cast(TemplateDeclaration)d) {
23 				// process members recursively
24 				// FIXME: Drops template parameters of outer eponymous templates.
25 				//        However, this is the same behavior as that of Ddoc.
26 				processDecls(templ.members);
27 
28 				// search for eponymous template members
29 				Declaration[] epmembers;
30 				foreach (m; templ.members)
31 					if (m.name == templ.name) {
32 						m.templateArgs = templ.templateArgs;
33 						m.templateConstraint = templ.templateConstraint;
34 						m.isTemplate = true;
35 						m.protection = templ.protection;
36 						m.parent = templ.parent;
37 						if (templ.docGroup.text.length)
38 							m.docGroup = templ.docGroup;
39 						m.inheritingDecl = templ.inheritingDecl;
40 						epmembers ~= m;
41 					}
42 
43 				if (epmembers.length > 0) {
44 					// if we found some, replace all references of the original template with the new modified members
45 					foreach (i, m; templ.docGroup.members) {
46 						if (m !is templ) continue;
47 						auto newm = templ.docGroup.members[0 .. i];
48 						foreach (epm; epmembers) newm ~= epm;
49 						newm ~= templ.docGroup.members[i+1 .. $];
50 						templ.docGroup.members = newm;
51 						break;
52 					}
53 					new_decls ~= epmembers;
54 				} else {
55 					// keep the template if there are no eponymous members
56 					new_decls ~= templ;
57 				}
58 			} else new_decls ~= d;
59 
60 			if (auto comp = cast(CompositeTypeDeclaration)d)
61 				processDecls(comp.members);
62 		}
63 		decls = new_decls;
64 	}
65 
66 	root.visit!Module((mod){
67 		processDecls(mod.members);
68 	});
69 }