D-Scanner/src/dscanner/analysis/local_imports.d

104 lines
2.3 KiB
D

// Copyright Brian Schott (Hackerpilot) 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module dscanner.analysis.local_imports;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
/**
* Checks for local imports that import all symbols.
* See_also: $(LINK https://issues.dlang.org/show_bug.cgi?id=10378)
*/
final class LocalImportCheck : BaseAnalyzer
{
alias visit = BaseAnalyzer.visit;
mixin AnalyzerInfo!"local_import_check";
/**
* Construct with the given file name.
*/
this(string fileName, const(Scope)* sc, bool skipTests = false)
{
super(fileName, sc, skipTests);
}
mixin visitThing!StructBody;
mixin visitThing!BlockStatement;
override void visit(const Declaration dec)
{
if (dec.importDeclaration is null)
{
dec.accept(this);
return;
}
foreach (attr; dec.attributes)
{
if (attr.attribute == tok!"static")
isStatic = true;
}
dec.accept(this);
isStatic = false;
}
override void visit(const ImportDeclaration id)
{
if ((!isStatic && interesting) && (id.importBindings is null
|| id.importBindings.importBinds.length == 0))
{
foreach (singleImport; id.singleImports)
{
if (singleImport.rename.text.length == 0)
{
addErrorMessage(singleImport,
"dscanner.suspicious.local_imports", "Local imports should specify"
~ " the symbols being imported to avoid hiding local symbols.");
}
}
}
}
private:
mixin template visitThing(T)
{
override void visit(const T thing)
{
const b = interesting;
interesting = true;
thing.accept(this);
interesting = b;
}
}
bool interesting;
bool isStatic;
}
unittest
{
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.local_import_check = Check.enabled;
assertAnalyzerWarnings(q{
void testLocalImport()
{
import std.stdio; /+
^^^^^^^^^ [warn]: Local imports should specify the symbols being imported to avoid hiding local symbols. +/
import std.fish : scales, head;
import DAGRON = std.experimental.dragon;
}
}c, sac);
stderr.writeln("Unittest for LocalImportCheck passed.");
}