1 // Copyright Brian Schott (Hackerpilot) 2014. 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 module dscanner.analysis.local_imports; 7 8 import std.stdio; 9 import dparse.ast; 10 import dparse.lexer; 11 import dscanner.analysis.base; 12 import dscanner.analysis.helpers; 13 import dsymbol.scope_; 14 15 /** 16 * Checks for local imports that import all symbols. 17 * See_also: $(LINK https://issues.dlang.org/show_bug.cgi?id=10378) 18 */ 19 class LocalImportCheck : BaseAnalyzer 20 { 21 alias visit = BaseAnalyzer.visit; 22 23 /** 24 * Construct with the given file name. 25 */ 26 this(string fileName, const(Scope)* sc, bool skipTests = false) 27 { 28 super(fileName, sc, skipTests); 29 } 30 31 mixin visitThing!StructBody; 32 mixin visitThing!BlockStatement; 33 34 override void visit(const Declaration dec) 35 { 36 if (dec.importDeclaration is null) 37 { 38 dec.accept(this); 39 return; 40 } 41 foreach (attr; dec.attributes) 42 { 43 if (attr.attribute == tok!"static") 44 isStatic = true; 45 } 46 dec.accept(this); 47 isStatic = false; 48 } 49 50 override void visit(const ImportDeclaration id) 51 { 52 if ((!isStatic && interesting) && (id.importBindings is null 53 || id.importBindings.importBinds.length == 0)) 54 { 55 foreach (singleImport; id.singleImports) 56 { 57 if (singleImport.rename.text.length == 0) 58 { 59 addErrorMessage(singleImport.identifierChain.identifiers[0].line, 60 singleImport.identifierChain.identifiers[0].column, 61 "dscanner.suspicious.local_imports", "Local imports should specify" 62 ~ " the symbols being imported to avoid hiding local symbols."); 63 } 64 } 65 } 66 } 67 68 private: 69 70 mixin template visitThing(T) 71 { 72 override void visit(const T thing) 73 { 74 const b = interesting; 75 interesting = true; 76 thing.accept(this); 77 interesting = b; 78 } 79 } 80 81 bool interesting; 82 bool isStatic; 83 } 84 85 unittest 86 { 87 import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; 88 89 StaticAnalysisConfig sac = disabledConfig(); 90 sac.local_import_check = Check.enabled; 91 assertAnalyzerWarnings(q{ 92 void testLocalImport() 93 { 94 import std.stdio; // [warn]: Local imports should specify the symbols being imported to avoid hiding local symbols. 95 import std.fish : scales, head; 96 import DAGRON = std.experimental.dragon; 97 } 98 }}, sac); 99 100 stderr.writeln("Unittest for LocalImportCheck passed."); 101 }