1 module glued.codescan.scanner; 2 3 import std.meta; 4 5 import glued.codescan.unrollscan; 6 public import glued.codescan.listener; 7 public import glued.codescan.scannable; 8 9 import glued.logging; 10 import glued.mirror; 11 12 class CodebaseScanner(State, Listeners...) 13 // if (__traits(compiles, new CompositeListener!(State, Listeners)())) //todo? 14 { 15 mixin CreateLogger; 16 private Logger log; 17 private bool _frozen = false; 18 private CompositeListener!(State, Listeners) listener = new CompositeListener!(State, Listeners); 19 20 this(State initialState, LogSink sink=new VoidSink) { 21 log = Logger(sink); 22 log.info.emit("Initializing scan listeners with ", initialState); 23 listener.init(initialState); 24 } 25 26 void scan(scannables...)() 27 { 28 static foreach (s; scannables){ 29 scan!s(); 30 } 31 } 32 33 void scan(alias scannable)() 34 if (isScannable!(scannable)) 35 { 36 //todo assert not frozen 37 //todo if we move these into private methods, we can log.trace whats going on 38 // enum typeConsumer(string m, string n) = "listener.onType!(import_!(\""~m~"\", \""~n~"\"))();"; 39 enum typeConsumer(string m, string n) = "onType!(\""~m~"\", \""~n~"\")();"; 40 enum bundleConsumer(string modName) = "listener.onBundleModule!(\""~modName~"\")();"; 41 42 mixin unrollLoopThrough!(scannable, "void doScan() { ", typeConsumer, bundleConsumer, "}"); 43 listener.onScannable!(scannable)(); 44 log.info.emit("Scanning ", scannable); 45 doScan(); 46 log.info.emit("Scan of ", scannable, " finished"); 47 } 48 49 private void onType(string m, string n)(){ 50 alias T = import_!(m, n); 51 listener.onType!T(); 52 } 53 54 void freeze(){ 55 log.info.emit("Freezing scanner"); 56 _frozen = true; 57 listener.onScannerFreeze(); 58 } 59 60 @property 61 bool frozen(){ 62 return _frozen; 63 } 64 } 65 66