1 // Copyright Brian Schott (Hackerpilot) 2016. 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.lambda_return_check; 7 8 import dparse.ast; 9 import dparse.lexer; 10 import dscanner.analysis.base; 11 import dscanner.utils : safeAccess; 12 13 final class LambdaReturnCheck : BaseAnalyzer 14 { 15 alias visit = BaseAnalyzer.visit; 16 17 this(string fileName, bool skipTests = false) 18 { 19 super(fileName, null, skipTests); 20 } 21 22 override void visit(const FunctionLiteralExpression fLit) 23 { 24 auto fe = safeAccess(fLit).assignExpression.as!UnaryExpression 25 .primaryExpression.functionLiteralExpression.unwrap; 26 27 if (fe is null || fe.parameters !is null || fe.identifier != tok!"" || 28 fe.specifiedFunctionBody is null || fe.specifiedFunctionBody.blockStatement is null) 29 { 30 return; 31 } 32 addErrorMessage(fLit.line, fLit.column, KEY, "This lambda returns a lambda. Add parenthesis to clarify."); 33 } 34 35 private: 36 enum KEY = "dscanner.confusing.lambda_returns_lambda"; 37 } 38 39 version(Windows) {/*because of newline in code*/} else 40 unittest 41 { 42 import dscanner.analysis.helpers : assertAnalyzerWarnings; 43 import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; 44 import std.stdio : stderr; 45 46 StaticAnalysisConfig sac = disabledConfig(); 47 sac.lambda_return_check = Check.enabled; 48 49 auto code = ` 50 void main() 51 { 52 int[] b; 53 auto a = b.map!(a => { return a * a + 2; }).array(); // [warn]: This lambda returns a lambda. Add parenthesis to clarify. 54 pragma(msg, typeof(a => { return a; })); // [warn]: This lambda returns a lambda. Add parenthesis to clarify. 55 pragma(msg, typeof((a) => { return a; })); // [warn]: This lambda returns a lambda. Add parenthesis to clarify. 56 pragma(msg, typeof({ return a; })); 57 pragma(msg, typeof(a => () { return a; })); 58 }`c; 59 assertAnalyzerWarnings(code, sac); 60 stderr.writeln("Unittest for LambdaReturnCheck passed."); 61 }