Last active
June 20, 2017 01:15
-
-
Save wilzbach/e5be1b0cbf21fba8bee5d4180874f6bf to your computer and use it in GitHub Desktop.
For all Dscanner checks find all failing module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env dub | |
/++ dub.sdl: | |
name "filter" | |
dependency "inifiled" version="~>1.0.1" | |
dependency "dscanner" version="~>0.4.0" | |
+/ | |
import analysis.config; | |
import dparse.lexer : StringCache; | |
import dsymbol.modulecache : ModuleCache; | |
import dparse.ast : Module; | |
import std.algorithm, std.file, std.parallelism, std.path, std.range, std.stdio, std.string; | |
void main(string[] args) { | |
string iniConfig = ".dscanner.ini"; | |
string phobosDir = "."; | |
string[] imports = ["."]; | |
StaticAnalysisConfig config; | |
import inifiled; | |
readINIFile(config, iniConfig); | |
auto fileNames = phobosDir | |
.dirEntries(SpanMode.depth) | |
.filter!(f => f.name.endsWith(".d")) | |
.filter!(f => !f.name.canFind("generated")) | |
.filter!(f => f.name.canFind("/std", "/etc")) | |
.filter!(f => !f.name.endsWith("std/traits.d", "std/typecons.d")) | |
.map!(f => f.name) | |
.array | |
.sort().release; | |
import std.typecons : scoped; | |
import dsymbol.modulecache : ASTAllocator; | |
StringCache cache = StringCache(StringCache.defaultBucketCount); | |
auto alloc = scoped!(ASTAllocator)(); | |
auto moduleCache = ModuleCache(alloc); | |
const(string[]) absImportPaths = imports.map!(a => a.absolutePath() | |
.buildNormalizedPath()).array(); | |
if (absImportPaths.length > 0) | |
moduleCache.addImportPaths(absImportPaths); | |
fileNames.writeln; | |
foreach (mem; __traits(allMembers, StaticAnalysisConfig)) | |
static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem)) == string)) | |
{ | |
mixin(`if (config.filters.` ~ mem ~ `.length > 0) { | |
config.filters.` ~ mem ~ ` = ["-foobar"]; | |
config.filters.` ~ mem ~ ` = checkConfig(fileNames, config, cache, moduleCache); | |
}`); | |
} | |
writeINIFile(config, iniConfig); | |
} | |
import std.stdio; | |
string[] checkConfig(string[] fileNames, StaticAnalysisConfig config, ref StringCache cache, ref ModuleCache moduleCache) | |
{ | |
string[] modules = []; | |
foreach (fileName; fileNames.parallel(1)) | |
{ | |
Module m; | |
fileName.writeln; | |
bool hasErrors = true; | |
try { | |
hasErrors = analyze(fileName, config, cache, moduleCache, true, m); | |
} catch(Exception) {} | |
catch(Error) {} | |
if (hasErrors) | |
{ | |
synchronized { | |
modules ~= "-" ~ m.moduleDeclaration.moduleName.identifiers.map!(m => m.text).join("."); | |
} | |
} | |
} | |
modules.writeln; | |
return modules.sort().release; | |
} | |
bool analyze(string fileName, const StaticAnalysisConfig config, | |
ref StringCache cache, ref ModuleCache moduleCache, bool staticAnalyze, | |
ref Module m2) | |
{ | |
import dparse.rollback_allocator : RollbackAllocator; | |
import dparse.lexer : Token; | |
import analysis.run : analyze, parseModule; | |
import readers : readFile; | |
bool hasErrors = false; | |
auto code = readFile(fileName); | |
RollbackAllocator r; | |
uint errorCount = 0; | |
uint warningCount = 0; | |
const(Token)[] tokens; | |
const Module m = parseModule(fileName, code, &r, cache, false, tokens, | |
null, &errorCount, &warningCount); | |
// workaround libparse's const (ugly) | |
m2 = cast(Module) m; | |
assert(m); | |
if (errorCount > 0 || (staticAnalyze && warningCount > 0)) | |
hasErrors = true; | |
auto results = analyze(fileName, m, config, moduleCache, tokens, staticAnalyze); | |
if (results is null) | |
return hasErrors; | |
foreach (result; results[]) | |
{ | |
hasErrors = true; | |
//writefln("%s(%d:%d)[warn]: %s", result.fileName, result.line, | |
//result.column, result.message); | |
} | |
return hasErrors; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment