<?xml version="1.0" encoding="UTF-8"?>

<ruleset name="Code Style"
         xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">

    <description>
Rules which enforce a specific coding style.
    </description>


    <rule name="AssignmentInOperand"
          language="ecmascript"
          since="5.0"
          message="Avoid assignments in operands"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#assignmentinoperand">
        <description>
Avoid assignments in operands; this can make code more complicated and harder to read.  This is sometime
indicative of the bug where the assignment operator '=' was used instead of the equality operator '=='.
        </description>
        <priority>2</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
    //IfStatement[$allowIf = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
|
    //WhileLoop[$allowWhile = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
|
    //DoLoop[$allowWhile = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
|
    //ForLoop[$allowFor = false()]/child::node()[2]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
|
   //ConditionalExpression[$allowTernary = false()]/child::node()[1]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
|
   //ConditionalExpression[$allowTernaryResults = false()]/child::node()[position() = 2 or position() = 3]/descendant-or-self::node()[self::Assignment or self::UpdateExpression[$allowIncrementDecrement = false() and @Operator = ('--', '++')]]
]]>
                </value>
            </property>
            <property name="allowIf" type="Boolean" value="false" description="Allow assignment within the conditional expression of an if statement" />
            <property name="allowFor" type="Boolean" value="false" description="Allow assignment within the conditional expression of a for statement" />
            <property name="allowWhile" type="Boolean" value="false" description="Allow assignment within the conditional expression of a while statement" />
            <property name="allowTernary" type="Boolean" value="false" description="Allow assignment within the conditional expression of a ternary operator" />
            <property name="allowTernaryResults" type="Boolean" value="false" description="Allow assignment within the result expressions of a ternary operator" />
            <property name="allowIncrementDecrement" type="Boolean" value="false" description="Allow increment or decrement operators within the conditional expression of an if, for, or while statement" />
        </properties>
        <example>
<![CDATA[
var x = 2;
// Bad
if ((x = getX()) == 3) {
    alert('3!');
}

function getX() {
    return 3;
}
]]>
        </example>
    </rule>

    <rule name="ForLoopsMustUseBraces"
          language="ecmascript"
          since="5.0"
          message="Avoid using 'for' statements without curly braces"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#forloopsmustusebraces">
        <description>
Avoid using 'for' statements without using curly braces.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ForLoop[not(child::Scope)]
|
//ForInLoop[not(child::Scope)]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Ok
for (var i = 0; i < 42; i++) {
    foo();
}

// Bad
for (var i = 0; i < 42; i++)
    foo();
]]>
        </example>
    </rule>

    <rule name="IfElseStmtsMustUseBraces"
          language="ecmascript"
          since="5.0"
          message="Avoid using 'if...else' statements without curly braces"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#ifelsestmtsmustusebraces">
        <description>
Avoid using if..else statements without using curly braces.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ExpressionStatement[parent::IfStatement[@Else = true()]]
   [not(child::Scope)]
   [not(child::IfStatement)]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Ok
if (foo) {
    x++;
} else {
    y++;
}

// Bad
if (foo)
    x++;
else
    y++;
]]>
        </example>
    </rule>

    <rule name="IfStmtsMustUseBraces"
          language="ecmascript"
          since="5.0"
          message="Avoid using if statements without curly braces"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#ifstmtsmustusebraces">
        <description>
Avoid using if statements without using curly braces.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//IfStatement[@Else = false() and not(child::Scope)]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Ok
if (foo) {
    x++;
}

// Bad
if (foo)
    x++;
]]>
        </example>
    </rule>

    <rule name="NoElseReturn"
          language="ecmascript"
          since="5.5.0"
          message="The else block is unnecessary"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#noelsereturn">
        <description>
The else block in a if-else-construct is unnecessary if the `if` block contains a return.
Then the content of the else block can be put outside.

See also: &lt;http://eslint.org/docs/rules/no-else-return>
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//IfStatement[@Else=true()][Scope[1]/ReturnStatement]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Bad:
if (x) {
    return y;
} else {
    return z;
}

// Good:
if (x) {
    return y;
}
return z;
]]>
        </example>
    </rule>

    <rule name="UnnecessaryBlock"
          language="ecmascript"
          since="5.0"
          message="Unnecessary block."
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unnecessaryblock">
        <description>
An unnecessary Block is present.  Such Blocks are often used in other languages to
introduce a new variable scope.  Blocks do not behave like this in ECMAScipt, and using them can
be misleading.  Considering removing this unnecessary Block.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value><![CDATA[
                      /AstRoot/Scope[not(preceding::EmptyStatement)]
                    | //SwitchCase[Scope]
                    | //(Scope|Block)[Scope|Block][count(*) = 1]
                ]]></value>
            </property>
        </properties>
        <example>
<![CDATA[
if (foo) {
    // Ok
}
if (bar) {
    {
        // Bad
    }
}
]]>
        </example>
    </rule>

    <rule name="UnnecessaryParentheses"
          language="ecmascript"
          since="5.0"
          message="Unnecessary parentheses."
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unnecessaryparentheses">
        <description>Unnecessary parentheses should be removed.</description>
        <priority>4</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//ParenthesizedExpression/ParenthesizedExpression
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
var x = 1; // Ok
var y = (1 + 1); // Ok
var z = ((1 + 1)); // Bad
]]>
        </example>
    </rule>

    <rule name="UnreachableCode"
          language="ecmascript"
          since="5.0"
          message="A ''return'', ''break'', ''continue'', or ''throw'' statement should be the last in a block."
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#unreachablecode">
        <description>
A 'return', 'break', 'continue', or 'throw' statement should be the last in a block. Statements after these
will never execute.  This is a bug, or extremely poor style.
        </description>
        <priority>1</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
    //ReturnStatement[following-sibling::node()]
|
    //ContinueStatement[following-sibling::node()]
|
    //BreakStatement[following-sibling::node()]
|
    //ThrowStatement[following-sibling::node()]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Ok
function foo() {
   return 1;
}
// Bad
function bar() {
   var x = 1;
   return x;
   x = 2;
}
]]>
        </example>
    </rule>

    <rule name="WhileLoopsMustUseBraces"
          language="ecmascript"
          since="5.0"
          message="Avoid using 'while' statements without curly braces"
          class="net.sourceforge.pmd.lang.rule.xpath.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/pmd_rules_ecmascript_codestyle.html#whileloopsmustusebraces">
        <description>
Avoid using 'while' statements without using curly braces.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
<![CDATA[
//WhileLoop[not(child::Scope)]
]]>
                </value>
            </property>
        </properties>
        <example>
<![CDATA[
// Ok
while (true) {
    x++;
}

// Bad
while (true)
    x++;
]]>
        </example>
    </rule>

</ruleset>
