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 import std..string : strip; 19 20 void processDecls(ref Declaration[] decls) 21 { 22 Declaration[] new_decls; 23 foreach (d; decls) { 24 if (auto templ = cast(TemplateDeclaration)d) { 25 // process members recursively 26 processDecls(templ.members); 27 28 // search for eponymous template members 29 Declaration[] epmembers; 30 bool[DocGroup] augmented_groups; 31 foreach (m; templ.members) 32 if (m.name == templ.name) { 33 // if we encounter any templated member, skip the 34 // eponymous merge and show individual members instead. 35 if (cast(TemplateDeclaration)m || m.templateArgs.length) { 36 epmembers = null; 37 break; 38 } 39 40 // if both, the parent template and the member are documented, 41 // abort the merge 42 if (templ.docGroup.text.strip.length && m.docGroup.text.strip.length) { 43 epmembers = null; 44 break; 45 } 46 47 m.templateArgs = templ.templateArgs; 48 m.templateConstraint = templ.templateConstraint; 49 m.isTemplate = true; 50 m.protection = templ.protection; 51 m.parent = templ.parent; 52 if (templ.docGroup.text.strip.length) m.docGroup = templ.docGroup; 53 m.inheritingDecl = templ.inheritingDecl; 54 epmembers ~= m; 55 } 56 57 if (epmembers.length > 0) { 58 // if we found some, replace all references of the original template with the new modified members 59 foreach (i, m; templ.docGroup.members) { 60 if (m !is templ) continue; 61 auto newm = templ.docGroup.members[0 .. i]; 62 foreach (epm; epmembers) 63 if (epm.docGroup is templ.docGroup) 64 newm ~= epm; 65 newm ~= templ.docGroup.members[i+1 .. $]; 66 templ.docGroup.members = newm; 67 break; 68 } 69 new_decls ~= epmembers; 70 } else { 71 // keep the template if there are no eponymous members 72 new_decls ~= templ; 73 } 74 } else new_decls ~= d; 75 76 if (auto comp = cast(CompositeTypeDeclaration)d) 77 processDecls(comp.members); 78 } 79 decls = new_decls; 80 } 81 82 root.visit!Module((mod){ 83 processDecls(mod.members); 84 }); 85 }