Merge pull request #388 from wilzbach/local-imports-sortedness

Imports sortedness check: handle local imports in their separate scope
This commit is contained in:
Brian Schott 2017-01-03 14:59:42 -08:00 committed by GitHub
commit 6ce77ecaed
1 changed files with 159 additions and 5 deletions

View File

@ -4,9 +4,9 @@
module analysis.imports_sortedness;
import analysis.base : BaseAnalyzer;
import dparse.lexer;
import dparse.ast;
import analysis.base : BaseAnalyzer;
import std.stdio;
@ -26,10 +26,32 @@ class ImportSortednessCheck : BaseAnalyzer
override void visit(const Module mod)
{
globalImports = [];
level = 0;
imports[level] = [];
mod.accept(this);
}
override void visit(const Statement decl)
{
imports[++level] = [];
decl.accept(this);
level--;
}
override void visit(const BlockStatement decl)
{
imports[++level] = [];
decl.accept(this);
level--;
}
override void visit(const StructBody decl)
{
imports[++level] = [];
decl.accept(this);
level--;
}
override void visit(const ImportDeclaration id)
{
import std.algorithm.iteration : map;
@ -59,20 +81,21 @@ class ImportSortednessCheck : BaseAnalyzer
private:
string[] globalImports;
int level = 0;
string[][int] imports;
void addImport(string importModuleName, const SingleImport singleImport)
{
import std.uni : sicmp;
if (globalImports.length > 0 && globalImports[$ -1].sicmp(importModuleName) > 0)
if (imports[level].length > 0 && imports[level][$ -1].sicmp(importModuleName) > 0)
{
addErrorMessage(singleImport.identifierChain.identifiers[0].line,
singleImport.identifierChain.identifiers[0].column, KEY, MESSAGE);
}
else
{
globalImports ~= importModuleName;
imports[level] ~= importModuleName;
}
}
}
@ -187,5 +210,136 @@ unittest
ImportSortednessCheck.MESSAGE,
), sac);
// local imports in functions
assertAnalyzerWarnings(q{
import t2;
import t1; // [warn]: %s
void foo()
{
import f2;
import f1; // [warn]: %s
import f3;
}
void bar()
{
import f1;
import f2;
}
}c.format(
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
), sac);
// local imports in scopes
assertAnalyzerWarnings(q{
import t2;
import t1; // [warn]: %s
void foo()
{
import f2;
import f1; // [warn]: %s
import f3;
{
import f2;
import f1; // [warn]: %s
import f3;
}
{
import f1;
import f2;
import f3;
}
}
}c.format(
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
), sac);
// local imports in functions
assertAnalyzerWarnings(q{
import t2;
import t1; // [warn]: %s
void foo()
{
import f2;
import f1; // [warn]: %s
import f3;
while (true) {
import f2;
import f1; // [warn]: %s
import f3;
}
for (;;) {
import f1;
import f2;
import f3;
}
foreach (el; arr) {
import f2;
import f1; // [warn]: %s
import f3;
}
}
}c.format(
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
), sac);
// nested scopes
assertAnalyzerWarnings(q{
import t2;
import t1; // [warn]: %s
void foo()
{
import f2;
import f1; // [warn]: %s
import f3;
{
import f2;
import f1; // [warn]: %s
import f3;
{
import f2;
import f1; // [warn]: %s
import f3;
{
import f2;
import f1; // [warn]: %s
import f3;
}
}
}
}
}c.format(
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
), sac);
// local imports in functions
assertAnalyzerWarnings(q{
import t2;
import t1; // [warn]: %s
struct foo()
{
import f2;
import f1; // [warn]: %s
import f3;
}
class bar()
{
import f1;
import f2;
}
}c.format(
ImportSortednessCheck.MESSAGE,
ImportSortednessCheck.MESSAGE,
), sac);
stderr.writeln("Unittest for ImportSortednessCheck passed.");
}