1 // Copyright Brian Schott (Hackerpilot) 2014-2015. 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 module dscanner.analysis.unused_parameter; 6 7 import dparse.ast; 8 import dparse.lexer; 9 import dscanner.analysis.base; 10 import dscanner.analysis.unused; 11 import dsymbol.scope_ : Scope; 12 13 /** 14 * Checks for unused variables. 15 */ 16 final class UnusedParameterCheck : UnusedStorageCheck 17 { 18 alias visit = UnusedStorageCheck.visit; 19 20 mixin AnalyzerInfo!"unused_parameter_check"; 21 22 /** 23 * Params: 24 * fileName = the name of the file being analyzed 25 */ 26 this(string fileName, const(Scope)* sc, bool skipTests = false) 27 { 28 super(fileName, sc, skipTests, "Parameter", "unused_parameter"); 29 } 30 31 override void visit(const Parameter parameter) 32 { 33 import std.algorithm : among; 34 import std.algorithm.iteration : filter; 35 import std.range : empty; 36 37 if (parameter.name != tok!"") 38 { 39 immutable bool isRef = !parameter.parameterAttributes 40 .filter!(a => a.idType.among(tok!"ref", tok!"out")).empty; 41 immutable bool isPtr = parameter.type && !parameter.type 42 .typeSuffixes.filter!(a => a.star != tok!"").empty; 43 44 variableDeclared(parameter.name.text, parameter.name.line, 45 parameter.name.column, isRef | isPtr); 46 47 if (parameter.default_ !is null) 48 { 49 interestDepth++; 50 parameter.default_.accept(this); 51 interestDepth--; 52 } 53 } 54 } 55 } 56 57 @system unittest 58 { 59 import std.stdio : stderr; 60 import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; 61 import dscanner.analysis.helpers : assertAnalyzerWarnings; 62 63 StaticAnalysisConfig sac = disabledConfig(); 64 sac.unused_parameter_check = Check.enabled; 65 assertAnalyzerWarnings(q{ 66 67 // bug encountered after correct DIP 1009 impl in dparse 68 version (StdDdoc) 69 { 70 bool isAbsolute(R)(R path) pure nothrow @safe 71 if (isRandomAccessRange!R && isSomeChar!(ElementType!R) || 72 is(StringTypeOf!R)); 73 } 74 75 void inPSC(in int a){} // [warn]: Parameter a is never used. 76 77 void doStuff(int a, int b) // [warn]: Parameter b is never used. 78 { 79 return a; 80 } 81 82 // Issue 352 83 void test352_1() 84 { 85 void f(int *x) {*x = 1;} 86 } 87 88 void test352_2() 89 { 90 void f(Bat** bat) {*bat = bats.ptr + 8;} 91 } 92 93 // Issue 490 94 void test490() 95 { 96 auto cb1 = delegate(size_t _) {}; 97 cb1(3); 98 auto cb2 = delegate(size_t a) {}; // [warn]: Parameter a is never used. 99 cb2(3); 100 } 101 102 bool hasDittos(int decl) 103 { 104 mixin("decl++;"); 105 } 106 107 // https://github.com/dlang-community/D-Scanner/issues/794 108 void traits() 109 { 110 struct S { int i; } 111 112 static foo(S s) 113 { 114 __traits(getMember, s, "i") = 99; 115 } 116 } 117 118 }}, sac); 119 stderr.writeln("Unittest for UnusedParameterCheck passed."); 120 }