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