Skip to content

Instantly share code, notes, and snippets.

@wilzbach
Last active June 20, 2017 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wilzbach/e5be1b0cbf21fba8bee5d4180874f6bf to your computer and use it in GitHub Desktop.
Save wilzbach/e5be1b0cbf21fba8bee5d4180874f6bf to your computer and use it in GitHub Desktop.
For all Dscanner checks find all failing module
#!/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