1 /** 2 Inherits non-existing members and documentation from anchestor classes/intefaces. 3 4 Copyright: © 2012 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.inherit; 9 10 import ddox.api; 11 import ddox.entities; 12 13 import std.algorithm : map; 14 15 16 void inheritDocs(Package root) 17 { 18 bool[CompositeTypeDeclaration] visited; 19 20 bool matches(Declaration a, Declaration b) 21 { 22 if (a.kind != b.kind) return false; 23 if (a.name != b.name) return false; 24 if (auto ctm = cast(TypedDeclaration)a) 25 if (ctm.type != (cast(TypedDeclaration)b).type) 26 return false; 27 return true; 28 } 29 30 Declaration findMatching(Declaration[] pool, Declaration match) 31 { 32 foreach (m; pool) { 33 if (matches(m, match)) 34 return m; 35 } 36 return null; 37 } 38 39 void inheritMembers(CompositeTypeDeclaration decl, Declaration[] parentmembers, const(Declaration) parent) 40 { 41 foreach (parentgrp; docGroups(parentmembers)) { 42 DocGroup inhgrp; 43 foreach (parentmem; parentgrp.members.map!(m => cast(Declaration)m)()) { 44 if (parentmem.name == "this") continue; 45 auto childmem = findMatching(decl.members, parentmem); 46 if (!childmem || !childmem.docGroup.text.length) { 47 Declaration newdecl; 48 if (childmem) newdecl = childmem; 49 else newdecl = parentmem.dup; 50 if (!inhgrp) inhgrp = new DocGroup(newdecl, parentgrp.text); 51 else inhgrp.members ~= newdecl; 52 newdecl.docGroup = inhgrp; 53 if (!childmem) { 54 newdecl.inheritingDecl = parentmem; 55 assert(newdecl.inheritingDecl && newdecl.inheritingDecl !is newdecl); 56 decl.members ~= newdecl; 57 } 58 } 59 } 60 } 61 } 62 63 void scanInterface(InterfaceDeclaration decl) 64 { 65 if (decl in visited) return; 66 foreach (i; decl.derivedInterfaces) 67 if (i.typeDecl) 68 scanInterface(cast(InterfaceDeclaration)i.typeDecl); 69 visited[decl] = true; 70 71 foreach (it; decl.derivedInterfaces) 72 if (it.typeDecl) 73 inheritMembers(decl, (cast(InterfaceDeclaration)it.typeDecl).members, it.typeDecl); 74 } 75 76 void scanClass(ClassDeclaration decl) 77 { 78 if (decl in visited) return; 79 80 visited[decl] = true; 81 82 if (decl.baseClass && decl.baseClass.typeDecl) scanClass(cast(ClassDeclaration)decl.baseClass.typeDecl); 83 84 foreach (i; decl.derivedInterfaces) 85 if (i.typeDecl) 86 scanInterface(cast(InterfaceDeclaration)i.typeDecl); 87 88 if (decl.baseClass && decl.baseClass.typeDecl) 89 inheritMembers(decl, (cast(ClassDeclaration)decl.baseClass.typeDecl).members, decl.baseClass.typeDecl); 90 foreach (i; decl.derivedInterfaces) 91 if (i.typeDecl) 92 inheritMembers(decl, (cast(InterfaceDeclaration)i.typeDecl).members, i.typeDecl); 93 } 94 95 void scanComposite(CompositeTypeDeclaration decl) 96 { 97 if (auto cd = cast(ClassDeclaration)decl) scanClass(cd); 98 else if (auto cd = cast(InterfaceDeclaration)decl) scanInterface(cd); 99 else { 100 foreach (m; decl.members) 101 if (auto dc = cast(CompositeTypeDeclaration)m) 102 scanComposite(dc); 103 } 104 } 105 106 void scanModule(Module mod) 107 { 108 foreach (d; mod.members) 109 if (auto dc = cast(CompositeTypeDeclaration)d) 110 scanComposite(dc); 111 } 112 113 void scanPackage(Package pack) 114 { 115 foreach (p; pack.packages) 116 scanPackage(p); 117 foreach (m; pack.modules) 118 scanModule(m); 119 } 120 121 scanPackage(root); 122 }