1 module cogito; 2 3 import dmd.frontend; 4 import dmd.astcodegen; 5 import dmd.errors; 6 import dmd.globals; 7 8 public import cogito.list; 9 public import cogito.meter; 10 public import cogito.visitor; 11 12 import std.algorithm; 13 import std.range; 14 15 private Result runOnFile(string file) 16 { 17 initialize(); 18 LocalHandler localHandler; 19 diagnosticHandler = &localHandler.handler; 20 21 scope (exit) 22 { 23 diagnosticHandler = null; 24 deinitialize(); 25 } 26 auto tree = parseModule!AST(file); 27 28 if (tree.diagnostics.hasErrors()) 29 { 30 return typeof(return)(localHandler.errors); 31 } 32 auto visitor = new CognitiveVisitor(file); 33 34 tree.module_.accept(visitor); 35 36 return typeof(return)(visitor.source); 37 } 38 39 /** 40 * Map a filename to an array of files. 41 * 42 * Params: 43 * filename = file or directory name. 44 * 45 * Returns: Array of filenames. 46 * If the filename points to a folder all d-files are returned, 47 * If the filename points to a file an array with only that file is returned. 48 */ 49 string[] toFiles(string filename) 50 { 51 import std.file : isFile, isDir, dirEntries, SpanMode; 52 if (filename.isFile) 53 { 54 return [filename]; 55 } 56 if (filename.isDir) 57 { 58 return filename 59 .dirEntries("*.d", SpanMode.breadth) 60 .filter!("a.isFile") 61 .map!("a.name") 62 .array; 63 } 64 import std.format : format; 65 throw new Exception(format!("%s is neither a file nor a directory")(filename)); 66 } 67 68 /** 69 * Measure the complexity in a list of modules. 70 * 71 * Params: 72 * args = File paths. 73 * 74 * Returns: List of collected scores in each file. 75 */ 76 auto runOnFiles(R)(R args) 77 if (isInputRange!R && is(ElementType!R == string)) 78 { 79 return args 80 .map!toFiles 81 .joiner 82 .array 83 .sort 84 .map!runOnFile; 85 } 86 87 /** 88 * Measure the complexity of the given code. 89 * 90 * Params: 91 * code = Code as string. 92 * 93 * Returns: Collected score. 94 */ 95 Result runOnCode(string code) 96 { 97 synchronized 98 { 99 initialize(); 100 LocalHandler localHandler; 101 scope (exit) 102 { 103 diagnosticHandler = null; 104 deinitialize(); 105 } 106 auto tree = parseModule!ASTCodegen("app.d", code); 107 108 if (tree.diagnostics.hasErrors()) 109 { 110 return typeof(return)(localHandler.errors); 111 } 112 auto visitor = new CognitiveVisitor(); 113 114 tree.module_.accept(visitor); 115 116 return typeof(return)(visitor.source); 117 } 118 }