D-Scanner/src/dscanner/analysis/logic_precedence.d

69 lines
1.8 KiB
D

// Copyright Brian Schott (Hackerpilot) 2014.
// 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 dscanner.analysis.logic_precedence;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
/**
* Checks for code with confusing && and || operator precedence
* ---
* if (a && b || c) // bad
* if (a && (b || c)) // good
* ---
*/
final class LogicPrecedenceCheck : BaseAnalyzer
{
alias visit = BaseAnalyzer.visit;
enum string KEY = "dscanner.confusing.logical_precedence";
mixin AnalyzerInfo!"logical_precedence_check";
this(BaseAnalyzerArguments args)
{
super(args);
}
override void visit(const OrOrExpression orOr)
{
if (orOr.left is null || orOr.right is null)
return;
const AndAndExpression left = cast(AndAndExpression) orOr.left;
const AndAndExpression right = cast(AndAndExpression) orOr.right;
if (left is null && right is null)
return;
if ((left !is null && left.right is null) && (right !is null && right.right is null))
return;
addErrorMessage(orOr, KEY,
"Use parenthesis to clarify this expression.");
orOr.accept(this);
}
}
unittest
{
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.logical_precedence_check = Check.enabled;
assertAnalyzerWarnings(q{
void testFish()
{
if (a && b || c) {} /+
^^^^^^^^^^^ [warn]: Use parenthesis to clarify this expression. +/
if ((a && b) || c) {} // Good
if (b || c && d) {} /+
^^^^^^^^^^^ [warn]: Use parenthesis to clarify this expression. +/
if (b || (c && d)) {} // Good
}
}c, sac);
stderr.writeln("Unittest for LogicPrecedenceCheck passed.");
}