1 module glued.adhesives.typeindex; 2 3 import std.array; 4 import std.algorithm.iteration; 5 6 import glued.logging; 7 8 import glued.set; 9 10 enum TypeKind { INTERFACE, ABSTRACT_CLASS, CONCRETE_CLASS } 11 12 class InheritanceIndex { 13 import std.algorithm; 14 TypeKind[string] kinds; 15 Set!(string)[string] implementations; 16 mixin CreateLogger; 17 Logger log; 18 19 this(LogSink logSink){ 20 log = Logger(logSink); 21 } 22 23 override string toString(){ 24 import std.conv: to; 25 string[] pairs; 26 foreach (k; implementations.keys()){ 27 pairs ~= "'"~k~"': Set!string("~to!string(implementations[k].asRange.array)~")"; 28 } 29 return typeof(this).stringof~"(kinds="~to!string(kinds)~", implementations=["~pairs.join(", ")~"])"; 30 } 31 32 void markExists(string query, TypeKind kind){ 33 log.debug_.emit(query, " is of kind ", kind); 34 if (query in kinds) 35 { 36 assert(kinds[query] == kind); //todo better exception 37 log.debug_.emit("Checks out with previous knowledge"); 38 } 39 else 40 { 41 kinds[query] = kind; 42 log.debug_.emit("That's new knowledge"); 43 } 44 } 45 46 void markExtends(string extending, string extended){ 47 log.debug_.emit(extending, " extends ", extended); 48 if (!(extended in implementations)) 49 implementations[extended] = Set!string(); 50 implementations[extended].put(extending); 51 } 52 53 TypeKind getTypeKind(string typeName){ 54 return TypeKind.INTERFACE; 55 } 56 57 Set!string getDirectSubtypes(string typeName){ 58 auto result = Set!string(); 59 if (typeName in implementations) { 60 result.addAll(implementations[typeName].asRange); 61 } 62 return result; 63 } 64 65 Set!string getSubtypes(string typeName){ 66 auto result = Set!string(); 67 auto direct = getDirectSubtypes(typeName); 68 auto indirect = direct.asRange.map!(d => getSubtypes(d).asRange.array).joiner; 69 result.addAll(direct.asRange); 70 result.addAll(indirect); 71 return result; 72 } 73 74 auto getImplementations(string typeName){ 75 return getSubtypes(typeName).asRange.filter!(n => kinds[n] == TypeKind.CONCRETE_CLASS); 76 } 77 78 auto getDirectImplementations(string typeName){ 79 return getDirectSubtypes(typeName).asRange.filter!(n => kinds[n] == TypeKind.CONCRETE_CLASS); 80 } 81 82 auto find(TypeKind kind){ 83 return kinds.keys().filter!(x => kinds[x] == kind); 84 } 85 86 }