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