1 module glued.scan; 2 3 import std.conv: to; 4 import std.traits; 5 import std.meta; 6 import std.string; 7 8 import glued.mirror; 9 import glued.utils; 10 11 public import glued.scannable; 12 13 string scanModule(string name, alias consumer)(){ 14 StringBuilder builder; 15 static if (!isGluedImplModule(name)) 16 { 17 mixin("static import "~name~";"); 18 mixin("alias mod_ = "~name~";"); 19 builder.append("static import "~name~";"); 20 //builder.append("alias mod_ = "~name~";"); 21 static foreach (alias mem; __traits(allMembers, mod_)){ 22 static if (__traits(compiles, __traits(getMember, mod_, mem))){ 23 static if (is(__traits(getMember, mod_, mem))){// && !is(__traits(getMember, mod_, mem) == enum)){ 24 builder.append(consumer!(name, mem)); 25 // BackboneContext.get().track!(Alias!(__traits(getMember, mod_, mem)))(); 26 } 27 } 28 } 29 } 30 return builder.result; 31 } 32 33 string scanIndexModule(string index, alias consumer)(){ 34 StringBuilder builder; 35 mixin("static import "~index~";"); 36 mixin("alias mod_ = "~index~";"); 37 38 static if (mod_.Index.importablePackage) 39 builder.append(scanModule!(mod_.Index.packageName, consumer)()); 40 static foreach (string submodule; EnumMembers!(mod_.Index.submodules)){ 41 builder.append(scanModule!(submodule, consumer)()); 42 } 43 static foreach (string subpackage; EnumMembers!(mod_.Index.subpackages)){ 44 builder.append(prepareScan!(subpackage, NoOp, NoOp, consumer, qualifier, testQualifier)()); //todo qualifiers 45 } 46 return builder.result; 47 } 48 49 bool isGluedImplModule(string name) 50 { 51 auto parts = name.split("."); 52 if (parts.length == 2) 53 return parts[0] == "glued"; 54 return false; 55 } 56 57 string prepareScan(alias roots, string setup, alias consumer, string teardown)(){ 58 StringBuilder builder; 59 builder.append(setup); 60 static foreach (alias scannable; roots) { 61 62 static assert(is(typeof(scannable) == Scannable)); //todo could be smartly expressed with conditional method 63 builder.append(scanIndexModule!(scannable.root~"."~scannable.prefix~"_index", consumer)()); 64 version(unittest){ 65 builder.append(scanIndexModule!(scannable.root~"."~scannable.testPrefix~"_index", consumer)()); 66 } 67 } 68 builder.append(teardown); 69 return builder.result; 70 } 71 72 enum NoOp = ""; 73 74 Scannable[] listScannables(Scannable s) { 75 return [s]; 76 } 77 78 Scannable[] listScannables(Scannable[] s){ 79 return s; 80 } 81 82 //not the nicest way, but it makes non-debug code nicer 83 //IMPORTANT modify both branches if you do anything here! 84 version(glued_debug) { 85 mixin template unrollLoopThrough(alias roots, string setup, alias consumer, string teardown, string f=__FILE__, int l=__LINE__){ 86 pragma(msg, "MIXING IN @",f, ":", l); 87 pragma(msg, prepareScan!(listScannables(roots), setup, consumer, teardown)()); 88 mixin(prepareScan!(listScannables(roots), setup, consumer, teardown)()); 89 } 90 } 91 else 92 { 93 mixin template unrollLoopThrough(alias roots, string setup, alias consumer, string teardown){ 94 mixin(prepareScan!(listScannables(roots), setup, consumer, teardown)()); 95 } 96 } 97 98