This commit is contained in:
Hackerpilot 2016-05-09 15:57:26 -07:00
parent e7a1b1fd2f
commit 15c780fac4
5 changed files with 76 additions and 2 deletions

View File

@ -7,7 +7,7 @@
"targetType": "executable",
"versions": ["built_with_dub"],
"dependencies": {
"libdparse": "~>0.7.0-alpha9",
"libdparse": "~>0.7.0-alpha10",
"dsymbol": "~>0.2.0-alpha6",
"inifiled": ">=0.0.6",
},

@ -1 +1 @@
Subproject commit 80f054e7d137de3b7907ee4a6406ffad5af9a6ea
Subproject commit c1dd27ea248111bd1dc9f8fb8a24f54592907110

View File

@ -116,4 +116,7 @@ struct StaticAnalysisConfig
@INI("Checks for else if that should be else static if")
bool static_if_else_check;
@INI("Check for unclear lambda syntax")
bool lambda_return_check;
}

View File

@ -0,0 +1,68 @@
// Copyright Brian Schott (Hackerpilot) 2016.
// 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 analysis.lambda_return_check;
import dparse.ast;
import dparse.lexer;
import analysis.base;
class LambdaReturnCheck : BaseAnalyzer
{
alias visit = BaseAnalyzer.visit;
this(string fileName)
{
super(fileName, null);
}
override void visit(const FunctionLiteralExpression fLit)
{
if (fLit.assignExpression is null)
return;
const UnaryExpression unary = cast(const UnaryExpression) fLit.assignExpression;
if (unary is null)
return;
if (unary.primaryExpression is null)
return;
if (unary.primaryExpression.functionLiteralExpression is null)
return;
if (unary.primaryExpression.functionLiteralExpression.parameters !is null)
return;
if (unary.primaryExpression.functionLiteralExpression.identifier != tok!"")
return;
if (unary.primaryExpression.functionLiteralExpression.functionBody is null)
return;
if (unary.primaryExpression.functionLiteralExpression.functionBody.blockStatement is null)
return;
addErrorMessage(fLit.line, fLit.column, KEY, "This lambda returns a lambda. Add parenthesis to clarify.");
}
private:
enum KEY = "dscanner.confusing.lambda_returns_lambda";
}
unittest
{
import analysis.helpers : assertAnalyzerWarnings;
import analysis.config : StaticAnalysisConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac;
sac.lambda_return_check = true;
auto code = `
void main()
{
int[] b;
auto a = b.map!(a => { return a * a + 2; }).array(); // [warn]: This lambda returns a lambda. Add parenthesis to clarify.
pragma(msg, typeof(a => { return a; })); // [warn]: This lambda returns a lambda. Add parenthesis to clarify.
pragma(msg, typeof((a) => { return a; })); // [warn]: This lambda returns a lambda. Add parenthesis to clarify.
pragma(msg, typeof({ return a; }));
pragma(msg, typeof(a => () { return a; }));
}`c;
assertAnalyzerWarnings(code, sac);
stderr.writeln("Unittest for LambdaReturnCheck passed.");
}

View File

@ -58,6 +58,7 @@ import analysis.incorrect_infinite_range;
import analysis.useless_assert;
import analysis.alias_syntax_check;
import analysis.static_if_else;
import analysis.lambda_return_check;
import dsymbol.string_interning : internString;
import dsymbol.scope_;
@ -276,6 +277,8 @@ MessageSet analyze(string fileName, const Module m, const StaticAnalysisConfig a
checks ~= new AliasSyntaxCheck(fileName);
if (analysisConfig.static_if_else_check)
checks ~= new StaticIfElse(fileName);
if (analysisConfig.lambda_return_check)
checks ~= new LambdaReturnCheck(fileName);
version (none)
if (analysisConfig.redundant_if_check)
checks ~= new IfStatementCheck(fileName, moduleScope);