Merge branch 'master' of github.com:pmd/pmd into lua-types

This commit is contained in:
Matt Hargett 2022-09-07 17:00:14 -07:00
commit c59ee1d55d
96 changed files with 1296 additions and 306 deletions

View File

@ -1053,7 +1053,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/86377278?v=4",
"profile": "https://github.com/aaronhurst-google",
"contributions": [
"bug"
"bug",
"code"
]
},
{
@ -5917,7 +5918,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/35368290?v=4",
"profile": "https://github.com/tprouvot",
"contributions": [
"bug"
"bug",
"code"
]
},
{
@ -6768,6 +6770,42 @@
"code",
"financial"
]
},
{
"login": "abyss638",
"name": "Simon Abykov",
"avatar_url": "https://avatars.githubusercontent.com/u/90252673?v=4",
"profile": "https://github.com/abyss638",
"contributions": [
"code"
]
},
{
"login": "eklimo",
"name": "Edward Klimoshenko",
"avatar_url": "https://avatars.githubusercontent.com/u/39220927?v=4",
"profile": "https://github.com/eklimo",
"contributions": [
"bug",
"code"
]
},
{
"login": "nvuillam",
"name": "Nicolas Vuillamy",
"avatar_url": "https://avatars.githubusercontent.com/u/17500430?v=4",
"profile": "https://github.com/nvuillam",
"contributions": [
"doc"
]
},{
"login": "pacvz",
"name": "pacvz",
"avatar_url": "https://avatars.githubusercontent.com/u/35453365?v=4",
"profile": "https://github.com/pacvz",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@ -27,6 +27,15 @@ function build() {
pmd_ci_utils_determine_build_env pmd/pmd
echo
if ! pmd_ci_utils_is_fork_or_pull_request; then
if [ "${PMD_CI_BRANCH}" = "experimental-apex-parser" ]; then
pmd_ci_log_group_start "Build with mvnw"
./mvnw clean install --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}"
pmd_ci_log_group_end
exit 0
fi
fi
if pmd_ci_utils_is_fork_or_pull_request; then
pmd_ci_log_group_start "Build with mvnw"
./mvnw clean install --show-version --errors --batch-mode --no-transfer-progress "${PMD_MAVEN_EXTRA_OPTS[@]}"

View File

@ -5,6 +5,7 @@ on:
branches:
- main
- master
- experimental-apex-parser
tags:
- '**'
pull_request:

View File

@ -1,9 +1,9 @@
repository: pmd/pmd
pmd:
version: 6.49.0-SNAPSHOT
previous_version: 6.48.0
date: 31-August-2022
version: 6.50.0-SNAPSHOT
previous_version: 6.49.0
date: 30-September-2022
release_type: minor
# release types: major, minor, bugfix

View File

@ -125,6 +125,23 @@ the breaking API changes will be performed in 7.0.0.
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
#### 6.49.0
##### Deprecated API
* In order to reduce the dependency on Apex Jorje classes, the following methods have been deprecated.
These methods all leaked internal Jorje enums. These enums have been replaced now by enums the
PMD's AST package.
* {% jdoc !!apex::lang.apex.ast.ASTAssignmentExpression#getOperator() %}
* {% jdoc !!apex::lang.apex.ast.ASTBinaryExpression#getOperator() %}
* {% jdoc !!apex::lang.apex.ast.ASTBooleanExpression#getOperator() %}
* {% jdoc !!apex::lang.apex.ast.ASTPostfixExpression#getOperator() %}
* {% jdoc !!apex::lang.apex.ast.ASTPrefixExpression#getOperator() %}
All these classes have now a new `getOp()` method. Existing code should be refactored to use this method instead.
It returns the new enums, like {% jdoc apex::lang.apex.ast.AssignmentOperator %}, and avoids
the dependency to Jorje.
#### 6.48.0
##### CPD CLI

File diff suppressed because it is too large Load Diff

View File

@ -104,9 +104,9 @@ Example:
<file path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java" totalNumberOfTokens="523"/>
<file path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java" totalNumberOfTokens="120"/>
<duplication lines="33" tokens="239">
<file column="29" endcolumn="75" endline="64" line="32"
<file column="29" endcolumn="75" endline="64" line="32" begintoken="2356" endtoken="2594"
path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java"/>
<file column="37" endcolumn="75" endline="100" line="68"
<file column="37" endcolumn="75" endline="100" line="68" begintoken="5700" endtoken="5938"
path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/RuleReferenceTest.java"/>
<codefragment><![CDATA[ public void testOverride() {
final StringProperty PROPERTY1_DESCRIPTOR = new StringProperty("property1", "Test property", null, 0f);
@ -143,11 +143,11 @@ Example:
validateOverriddenValues(PROPERTY1_DESCRIPTOR, PROPERTY2_DESCRIPTOR, ruleReference);]]></codefragment>
</duplication>
<duplication lines="16" tokens="110">
<file column="9" endcolumn="28" endline="81" line="66"
<file column="9" endcolumn="28" endline="81" line="66" begintoken="3000" endtoken="3109"
path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
<file column="9" endcolumn="28" endline="103" line="88"
<file column="9" endcolumn="28" endline="103" line="88" begintoken="3200" endtoken="3309"
path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
<file column="9" endcolumn="28" endline="125" line="110"
<file column="9" endcolumn="28" endline="125" line="110" begintoken="3400" endtoken="3509"
path="/home/pmd/source/pmd-core/src/test/java/net/sourceforge/pmd/lang/rule/xpath/JaxenXPathRuleQueryTest.java"/>
<codefragment><![CDATA[ JaxenXPathRuleQuery query = createQuery(xpath);
List<String> ruleChainVisits = query.getRuleChainVisits();

View File

@ -28,4 +28,10 @@ result of the PMD maven plugin.
See [Other Tools / Integrations](pmd_userdocs_tools.html#github-actions)
## MegaLinter
[🦙 Mega-Linter](https://oxsecurity.github.io/megalinter/latest/) analyzes 50 languages, 22 formats, 21 tooling formats, excessive copy-pastes, spelling mistakes and security issues in your repository sources with a GitHub Action, other CI tools or locally.
It [natively embeds PMD](https://oxsecurity.github.io/megalinter/latest/descriptors/java_pmd/).
<!-- TODO: Find out about other plugins ? -->

View File

@ -5,6 +5,69 @@ permalink: pmd_release_notes_old.html
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
## 31-August-2022 - 6.49.0
The PMD team is pleased to announce PMD 6.49.0.
This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [Updated PMD Designer](#updated-pmd-designer)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [Deprecated API](#deprecated-api)
* [External Contributions](#external-contributions)
* [Stats](#stats)
### New and noteworthy
#### Updated PMD Designer
This PMD release ships a new version of the pmd-designer.
For the changes, see [PMD Designer Changelog](https://github.com/pmd/pmd-designer/releases/tag/6.49.0).
### Fixed Issues
* apex
* [#4096](https://github.com/pmd/pmd/issues/4096): \[apex] ApexAssertionsShouldIncludeMessage and ApexUnitTestClassShouldHaveAsserts: support new Assert class (introduced with Apex v56.0)
* core
* [#3970](https://github.com/pmd/pmd/issues/3970): \[core] FileCollector.addFile ignores language parameter
* java-codestyle
* [#4082](https://github.com/pmd/pmd/issues/4082): \[java] UnnecessaryImport false positive for on-demand imports of nested classes
### API Changes
#### Deprecated API
* In order to reduce the dependency on Apex Jorje classes, the following methods have been deprecated.
These methods all leaked internal Jorje enums. These enums have been replaced now by enums the
PMD's AST package.
* <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/ASTAssignmentExpression.html#getOperator()"><code>ASTAssignmentExpression#getOperator</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/ASTBinaryExpression.html#getOperator()"><code>ASTBinaryExpression#getOperator</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/ASTBooleanExpression.html#getOperator()"><code>ASTBooleanExpression#getOperator</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/ASTPostfixExpression.html#getOperator()"><code>ASTPostfixExpression#getOperator</code></a>
* <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/ASTPrefixExpression.html#getOperator()"><code>ASTPrefixExpression#getOperator</code></a>
All these classes have now a new `getOp()` method. Existing code should be refactored to use this method instead.
It returns the new enums, like <a href="https://docs.pmd-code.org/apidocs/pmd-apex/6.49.0/net/sourceforge/pmd/lang/apex/ast/AssignmentOperator.html#"><code>AssignmentOperator</code></a>, and avoids
the dependency to Jorje.
### External Contributions
* [#4081](https://github.com/pmd/pmd/pull/4081): \[apex] Remove Jorje leaks outside `ast` package - [@eklimo](https://github.com/eklimo)
* [#4083](https://github.com/pmd/pmd/pull/4083): \[java] UnnecessaryImport false positive for on-demand imports of nested classes (fix for #4082) - [@abyss638](https://github.com/abyss638)
* [#4092](https://github.com/pmd/pmd/pull/4092): \[apex] Implement ApexQualifiableNode for ASTUserEnum - [@aaronhurst-google](https://github.com/aaronhurst-google)
* [#4095](https://github.com/pmd/pmd/pull/4095): \[core] CPD: Added begin and end token to XML reports - [@pacvz](https://github.com/pacvz)
* [#4097](https://github.com/pmd/pmd/pull/4097): \[apex] ApexUnitTestClassShouldHaveAssertsRule: Support new Assert class (Apex v56.0) - [@tprouvot](https://github.com/tprouvot)
* [#4104](https://github.com/pmd/pmd/pull/4104): \[doc] Add MegaLinter in the list of integrations - [@nvuillam](https://github.com/nvuillam)
### Stats
* 49 commits
* 10 closed tickets & PRs
* Days since last release: 32
## 30-July-2022 - 6.48.0
The PMD team is pleased to announce PMD 6.48.0.

View File

@ -8,7 +8,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.49.0-SNAPSHOT</version>
<version>6.50.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>net.sourceforge.pmd</groupId>
<artifactId>pmd</artifactId>
<version>6.49.0-SNAPSHOT</version>
<version>6.50.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -22,7 +22,15 @@ public class ASTAssignmentExpression extends AbstractApexNode<AssignmentExpressi
return visitor.visit(this, data);
}
/**
* @deprecated Use {@link #getOp()} instead.
*/
@Deprecated
public AssignmentOp getOperator() {
return node.getOp();
}
public AssignmentOperator getOp() {
return AssignmentOperator.valueOf(node.getOp());
}
}

View File

@ -22,7 +22,15 @@ public class ASTBinaryExpression extends AbstractApexNode<BinaryExpression> {
return visitor.visit(this, data);
}
/**
* @deprecated Use {@link #getOp()} instead.
*/
@Deprecated
public BinaryOp getOperator() {
return node.getOp();
}
public BinaryOperator getOp() {
return BinaryOperator.valueOf(node.getOp());
}
}

View File

@ -24,9 +24,15 @@ public class ASTBooleanExpression extends AbstractApexNode<BooleanExpression> {
return visitor.visit(this, data);
}
/**
* @deprecated Use {@link #getOp()} instead.
*/
@Deprecated
public BooleanOp getOperator() {
return this.node.getOp();
}
public BooleanOperator getOp() {
return BooleanOperator.valueOf(this.node.getOp());
}
}

View File

@ -24,8 +24,15 @@ public class ASTPostfixExpression extends AbstractApexNode<PostfixExpression> {
return visitor.visit(this, data);
}
/**
* @deprecated Use {@link #getOp()} instead.
*/
@Deprecated
public PostfixOp getOperator() {
return node.getOp();
}
public PostfixOperator getOp() {
return PostfixOperator.valueOf(node.getOp());
}
}

View File

@ -22,8 +22,15 @@ public class ASTPrefixExpression extends AbstractApexNode<PrefixExpression> {
return visitor.visit(this, data);
}
/**
* @deprecated Use {@link #getOp()} instead.
*/
@Deprecated
public PrefixOp getOperator() {
return node.getOp();
}
public PrefixOperator getOp() {
return PrefixOperator.valueOf(node.getOp());
}
}

View File

@ -8,7 +8,9 @@ import net.sourceforge.pmd.annotation.InternalApi;
import apex.jorje.semantic.ast.compilation.UserEnum;
public class ASTUserEnum extends ApexRootNode<UserEnum> {
public class ASTUserEnum extends ApexRootNode<UserEnum> implements ApexQualifiableNode {
private ApexQualifiedName qname;
@Deprecated
@InternalApi
@ -30,4 +32,20 @@ public class ASTUserEnum extends ApexRootNode<UserEnum> {
public ASTModifierNode getModifiers() {
return getFirstChildOfType(ASTModifierNode.class);
}
@Override
public ApexQualifiedName getQualifiedName() {
if (qname == null) {
ASTUserClass parent = this.getFirstParentOfType(ASTUserClass.class);
if (parent != null) {
qname = ApexQualifiedName.ofNestedEnum(parent.getQualifiedName(), this);
} else {
qname = ApexQualifiedName.ofOuterEnum(this);
}
}
return qname;
}
}

View File

@ -148,6 +148,20 @@ public final class ApexQualifiedName implements QualifiedName {
}
static ApexQualifiedName ofOuterEnum(ASTUserEnum astUserEnum) {
String ns = astUserEnum.getNamespace();
String[] classes = {astUserEnum.getImage()};
return new ApexQualifiedName(StringUtils.isEmpty(ns) ? "c" : ns, classes, null);
}
static ApexQualifiedName ofNestedEnum(ApexQualifiedName parent, ASTUserEnum astUserEnum) {
String[] classes = Arrays.copyOf(parent.classes, parent.classes.length + 1);
classes[classes.length - 1] = astUserEnum.getImage();
return new ApexQualifiedName(parent.nameSpace, classes, null);
}
private static String getOperationString(ASTMethod node) {
StringBuilder sb = new StringBuilder();
sb.append(node.getImage()).append('(');
@ -171,18 +185,28 @@ public final class ApexQualifiedName implements QualifiedName {
static ApexQualifiedName ofMethod(ASTMethod node) {
ASTUserClassOrInterface<?> parent = node.getFirstParentOfType(ASTUserClassOrInterface.class);
if (parent == null) {
ASTUserTrigger trigger = node.getFirstParentOfType(ASTUserTrigger.class);
String ns = trigger.getNamespace();
String targetObj = trigger.getTargetName();
return new ApexQualifiedName(StringUtils.isEmpty(ns) ? "c" : ns, new String[]{"trigger", targetObj}, trigger.getImage()); // uses a reserved word as a class name to prevent clashes
} else {
ApexQualifiedName baseName = parent.getQualifiedName();
// Check first, as enum must be innermost potential parent
ASTUserEnum enumParent = node.getFirstParentOfType(ASTUserEnum.class);
if (enumParent != null) {
ApexQualifiedName baseName = enumParent.getQualifiedName();
return new ApexQualifiedName(baseName.nameSpace, baseName.classes, getOperationString(node));
}
ASTUserClassOrInterface<?> classParent = node.getFirstParentOfType(ASTUserClassOrInterface.class);
if (classParent != null) {
ApexQualifiedName baseName = classParent.getQualifiedName();
return new ApexQualifiedName(baseName.nameSpace, baseName.classes, getOperationString(node));
}
ASTUserTrigger triggerParent = node.getFirstParentOfType(ASTUserTrigger.class);
if (triggerParent != null) {
String ns = triggerParent.getNamespace();
String targetObj = triggerParent.getTargetName();
return new ApexQualifiedName(StringUtils.isEmpty(ns) ? "c" : ns, new String[]{"trigger", targetObj}, triggerParent.getImage()); // uses a reserved word as a class name to prevent clashes
}
throw new UnsupportedOperationException();
}
}

View File

@ -8,12 +8,12 @@ import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.ast.SourceCodePositioner;
import apex.jorje.semantic.ast.AstNode;
import apex.jorje.semantic.ast.compilation.Compilation;
import apex.jorje.services.Version;
@Deprecated
@InternalApi
public abstract class ApexRootNode<T extends AstNode> extends AbstractApexNode<T> implements RootNode {
public abstract class ApexRootNode<T extends Compilation> extends AbstractApexNode<T> implements RootNode {
@Deprecated
@InternalApi
public ApexRootNode(T node) {

View File

@ -0,0 +1,67 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import apex.jorje.data.ast.AssignmentOp;
/**
* Apex assignment operator
*/
public enum AssignmentOperator {
EQUALS("="),
ADDITION_EQUALS("+="),
SUBTRACTION_EQUALS("-="),
MULTIPLICATION_EQUALS("*="),
DIVISION_EQUALS("/="),
LEFT_SHIFT_EQUALS("<<="),
RIGHT_SHIFT_SIGNED_EQUALS(">>="),
RIGHT_SHIFT_UNSIGNED_EQUALS(">>>="),
BITWISE_AND_EQUALS("&="),
BITWISE_OR_EQUALS("|="),
BITWISE_XOR_EQUALS("^=");
private final String symbol;
AssignmentOperator(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
/**
* Returns a {@link AssignmentOperator} corresponding to the given {@link AssignmentOp}.
*/
public static AssignmentOperator valueOf(AssignmentOp op) {
switch (op) {
case EQUALS:
return EQUALS;
case ADDITION_EQUALS:
return ADDITION_EQUALS;
case SUBTRACTION_EQUALS:
return SUBTRACTION_EQUALS;
case MULTIPLICATION_EQUALS:
return MULTIPLICATION_EQUALS;
case DIVISION_EQUALS:
return DIVISION_EQUALS;
case LEFT_SHIFT_EQUALS:
return LEFT_SHIFT_EQUALS;
case RIGHT_SHIFT_EQUALS:
return RIGHT_SHIFT_SIGNED_EQUALS;
case UNSIGNED_RIGHT_SHIFT_EQUALS:
return RIGHT_SHIFT_UNSIGNED_EQUALS;
case AND_EQUALS:
return BITWISE_AND_EQUALS;
case OR_EQUALS:
return BITWISE_OR_EQUALS;
case XOR_EQUALS:
return BITWISE_XOR_EQUALS;
default:
throw new IllegalArgumentException("Invalid assignment operator " + op);
}
}
}

View File

@ -0,0 +1,64 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import apex.jorje.data.ast.BinaryOp;
/**
* Apex binary operator
*/
public enum BinaryOperator {
ADDITION("+"),
SUBTRACTION("-"),
MULTIPLICATION("*"),
DIVISION("/"),
LEFT_SHIFT("<<"),
RIGHT_SHIFT_SIGNED(">>"),
RIGHT_SHIFT_UNSIGNED(">>>"),
BITWISE_AND("&"),
BITWISE_OR("|"),
BITWISE_XOR("^");
private final String symbol;
BinaryOperator(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
/**
* Returns a {@link BinaryOperator} corresponding to the given {@link BinaryOp}.
*/
public static BinaryOperator valueOf(BinaryOp op) {
switch (op) {
case ADDITION:
return ADDITION;
case SUBTRACTION:
return SUBTRACTION;
case MULTIPLICATION:
return MULTIPLICATION;
case DIVISION:
return DIVISION;
case LEFT_SHIFT:
return LEFT_SHIFT;
case RIGHT_SHIFT:
return RIGHT_SHIFT_SIGNED;
case UNSIGNED_RIGHT_SHIFT:
return RIGHT_SHIFT_UNSIGNED;
case AND:
return BITWISE_AND;
case OR:
return BITWISE_OR;
case XOR:
return BITWISE_XOR;
default:
throw new IllegalArgumentException("Invalid binary operator " + op);
}
}
}

View File

@ -0,0 +1,67 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import apex.jorje.data.ast.BooleanOp;
/**
* Apex boolean operator
*/
public enum BooleanOperator {
EQUAL("=="),
NOT_EQUAL("!="),
ALT_NOT_EQUAL("<>"),
EXACTLY_EQUAL("==="),
EXACTLY_NOT_EQUAL("!=="),
LESS_THAN("<"),
GREATER_THAN(">"),
LESS_THAN_OR_EQUAL("<="),
GREATER_THAN_OR_EQUAL(">="),
LOGICAL_AND("&&"),
LOGICAL_OR("||");
private final String symbol;
BooleanOperator(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
/**
* Returns a {@link BooleanOperator} corresponding to the given {@link BooleanOp}.
*/
public static BooleanOperator valueOf(BooleanOp op) {
switch (op) {
case DOUBLE_EQUAL:
return EQUAL;
case NOT_EQUAL:
return NOT_EQUAL;
case ALT_NOT_EQUAL:
return ALT_NOT_EQUAL;
case TRIPLE_EQUAL:
return EXACTLY_EQUAL;
case NOT_TRIPLE_EQUAL:
return EXACTLY_NOT_EQUAL;
case LESS_THAN:
return LESS_THAN;
case GREATER_THAN:
return GREATER_THAN;
case LESS_THAN_EQUAL:
return LESS_THAN_OR_EQUAL;
case GREATER_THAN_EQUAL:
return GREATER_THAN_OR_EQUAL;
case AND:
return LOGICAL_AND;
case OR:
return LOGICAL_OR;
default:
throw new IllegalArgumentException("Invalid boolean operator " + op);
}
}
}

View File

@ -0,0 +1,40 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import apex.jorje.data.ast.PostfixOp;
/**
* Apex postfix operator
*/
public enum PostfixOperator {
INCREMENT("++"),
DECREMENT("--");
private final String symbol;
PostfixOperator(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
/**
* Returns a {@link PostfixOperator} corresponding to the given {@link PostfixOp}.
*/
public static PostfixOperator valueOf(PostfixOp op) {
switch (op) {
case INC:
return INCREMENT;
case DEC:
return DECREMENT;
default:
throw new IllegalArgumentException("Invalid postfix operator " + op);
}
}
}

View File

@ -0,0 +1,52 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import apex.jorje.data.ast.PrefixOp;
/**
* Apex prefix operator
*/
public enum PrefixOperator {
POSITIVE("+"),
NEGATIVE("-"),
LOGICAL_NOT("!"),
BITWISE_NOT("~"),
INCREMENT("++"),
DECREMENT("--");
private final String symbol;
PrefixOperator(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return this.symbol;
}
/**
* Returns a {@link PrefixOperator} corresponding to the given {@link PrefixOp}.
*/
public static PrefixOperator valueOf(PrefixOp op) {
switch (op) {
case POSITIVE:
return POSITIVE;
case NEGATIVE:
return NEGATIVE;
case NOT:
return LOGICAL_NOT;
case BITWISE_COMPLEMENT:
return BITWISE_NOT;
case INC:
return INCREMENT;
case DEC:
return DECREMENT;
default:
throw new IllegalArgumentException("Invalid prefix operator " + op);
}
}
}

View File

@ -12,11 +12,10 @@ import org.apache.commons.lang3.mutable.MutableInt;
import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression;
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
import net.sourceforge.pmd.lang.apex.ast.ASTStandardCondition;
import net.sourceforge.pmd.lang.apex.ast.BooleanOperator;
import net.sourceforge.pmd.lang.apex.metrics.impl.visitors.StandardCycloVisitor;
import net.sourceforge.pmd.lang.metrics.MetricOptions;
import apex.jorje.data.ast.BooleanOp;
/**
* See the doc for the Java metric.
*
@ -44,8 +43,8 @@ public class CycloMetric extends AbstractApexOperationMetric {
int complexity = 0;
for (ASTBooleanExpression sub : subs) {
BooleanOp op = sub.getOperator();
if (op != null && (op == BooleanOp.AND || op == BooleanOp.OR)) {
BooleanOperator op = sub.getOp();
if (op == BooleanOperator.LOGICAL_AND || op == BooleanOperator.LOGICAL_OR) {
complexity++;
}
}

View File

@ -19,9 +19,8 @@ import net.sourceforge.pmd.lang.apex.ast.ASTTernaryExpression;
import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement;
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter;
import apex.jorje.data.ast.BooleanOp;
import apex.jorje.data.ast.PrefixOp;
import net.sourceforge.pmd.lang.apex.ast.BooleanOperator;
import net.sourceforge.pmd.lang.apex.ast.PrefixOperator;
/**
* @author Gwilym Kuiper
@ -31,7 +30,7 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter {
private int complexity = 0;
private int nestingLevel = 0;
private BooleanOp currentBooleanOperation = null;
private BooleanOperator currentBooleanOperation = null;
private String methodName = null;
public double getComplexity() {
@ -53,7 +52,7 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter {
complexity++;
}
void booleanOperation(BooleanOp op) {
void booleanOperation(BooleanOperator op) {
if (currentBooleanOperation != op) {
if (op != null) {
fundamentalComplexity();
@ -177,8 +176,8 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter {
public Object visit(ASTBooleanExpression node, Object data) {
State state = (State) data;
BooleanOp op = node.getOperator();
if (op == BooleanOp.AND || op == BooleanOp.OR) {
BooleanOperator op = node.getOp();
if (op == BooleanOperator.LOGICAL_AND || op == BooleanOperator.LOGICAL_OR) {
state.booleanOperation(op);
}
@ -189,8 +188,8 @@ public class CognitiveComplexityVisitor extends ApexParserVisitorAdapter {
public Object visit(ASTPrefixExpression node, Object data) {
State state = (State) data;
PrefixOp op = node.getOperator();
if (op == PrefixOp.NOT) {
PrefixOperator op = node.getOp();
if (op == PrefixOperator.LOGICAL_NOT) {
state.booleanOperation(null);
}

View File

@ -12,17 +12,39 @@ public class ApexAssertionsShouldIncludeMessageRule extends AbstractApexUnitTest
private static final String ASSERT = "System.assert";
private static final String ASSERT_EQUALS = "System.assertEquals";
private static final String ASSERT_NOT_EQUALS = "System.assertNotEquals";
private static final String ARE_EQUAL = "Assert.areEqual";
private static final String ARE_NOT_EQUAL = "Assert.areNotEqual";
private static final String IS_FALSE = "Assert.isFalse";
private static final String FAIL = "Assert.fail";
private static final String IS_INSTANCE_OF_TYPE = "Assert.isInstanceOfType";
private static final String IS_NOT_INSTANCE_OF_TYPE = "Assert.isNotInstanceOfType";
private static final String IS_NOT_NULL = "Assert.isNotNull";
private static final String IS_NULL = "Assert.isNull";
private static final String IS_TRUE = "Assert.isTrue";
@Override
public Object visit(ASTMethodCallExpression node, Object data) {
String methodName = node.getFullMethodName();
if (ASSERT.equalsIgnoreCase(methodName) && node.getNumChildren() == 2) {
if (FAIL.equalsIgnoreCase(methodName) && node.getNumChildren() == 1) {
addViolationWithMessage(data, node,
"''{0}'' should have 1 parameters.",
new Object[] { FAIL });
} else if ((ASSERT.equalsIgnoreCase(methodName)
|| IS_FALSE.equalsIgnoreCase(methodName)
|| IS_NOT_NULL.equalsIgnoreCase(methodName)
|| IS_NULL.equalsIgnoreCase(methodName)
|| IS_TRUE.equalsIgnoreCase(methodName))
&& node.getNumChildren() == 2) {
addViolationWithMessage(data, node,
"''{0}'' should have 2 parameters.",
new Object[] { ASSERT });
new Object[] { methodName });
} else if ((ASSERT_EQUALS.equalsIgnoreCase(methodName)
|| ASSERT_NOT_EQUALS.equalsIgnoreCase(methodName))
|| ASSERT_NOT_EQUALS.equalsIgnoreCase(methodName)
|| ARE_EQUAL.equalsIgnoreCase(methodName)
|| ARE_NOT_EQUAL.equalsIgnoreCase(methodName)
|| IS_INSTANCE_OF_TYPE.equalsIgnoreCase(methodName)
|| IS_NOT_INSTANCE_OF_TYPE.equalsIgnoreCase(methodName))
&& node.getNumChildren() == 3) {
addViolationWithMessage(data, node,
"''{0}'' should have 3 parameters.",

View File

@ -37,18 +37,39 @@ public class ApexUnitTestClassShouldHaveAssertsRule extends AbstractApexUnitTest
ASSERT_METHODS.add("system.assert");
ASSERT_METHODS.add("system.assertequals");
ASSERT_METHODS.add("system.assertnotequals");
ASSERT_METHODS.add("assert.areequal");
ASSERT_METHODS.add("assert.arenotequal");
ASSERT_METHODS.add("assert.fail");
ASSERT_METHODS.add("assert.isfalse");
ASSERT_METHODS.add("assert.isinstanceoftype");
ASSERT_METHODS.add("assert.isnotinstanceoftype");
ASSERT_METHODS.add("assert.isnull");
ASSERT_METHODS.add("assert.isnotnull");
ASSERT_METHODS.add("assert.istrue");
// Fully-qualified variants...rare but still valid/possible
ASSERT_METHODS.add("system.system.assert");
ASSERT_METHODS.add("system.system.assertequals");
ASSERT_METHODS.add("system.system.assertnotequals");
ASSERT_METHODS.add("system.assert.areequal");
ASSERT_METHODS.add("system.assert.arenotequal");
ASSERT_METHODS.add("system.assert.fail");
ASSERT_METHODS.add("system.assert.isfalse");
ASSERT_METHODS.add("system.assert.isinstanceoftype");
ASSERT_METHODS.add("system.assert.isnotinstanceoftype");
ASSERT_METHODS.add("system.assert.isnull");
ASSERT_METHODS.add("system.assert.isnotnull");
ASSERT_METHODS.add("system.assert.istrue");
}
// Using a string property instead of a regex property to ensure that the compiled pattern can be case-insensitive
private static final PropertyDescriptor<String> ADDITIONAL_ASSERT_METHOD_PATTERN_DESCRIPTOR =
stringProperty("additionalAssertMethodPattern")
.desc("A regular expression for one or more custom test assertion method patterns.").defaultValue("").build();
// Using a string property instead of a regex property to ensure that the
// compiled pattern can be case-insensitive
private static final PropertyDescriptor<String> ADDITIONAL_ASSERT_METHOD_PATTERN_DESCRIPTOR = stringProperty(
"additionalAssertMethodPattern")
.desc("A regular expression for one or more custom test assertion method patterns.").defaultValue("")
.build();
// A simple compiled pattern cache to ensure that we only ever try to compile the configured pattern once for a given run
// A simple compiled pattern cache to ensure that we only ever try to compile
// the configured pattern once for a given run
private Optional<Pattern> compiledAdditionalAssertMethodPattern = null;
public ApexUnitTestClassShouldHaveAssertsRule() {
@ -81,7 +102,8 @@ public class ApexUnitTestClassShouldHaveAssertsRule extends AbstractApexUnitTest
}
}
// If we didn't find assert method invocations the simple way and we have a configured pattern, try it
// If we didn't find assert method invocations the simple way and we have a
// configured pattern, try it
if (!isAssertFound) {
final String additionalAssertMethodPattern = getProperty(ADDITIONAL_ASSERT_METHOD_PATTERN_DESCRIPTOR);
final Pattern compiledPattern = getCompiledAdditionalAssertMethodPattern(additionalAssertMethodPattern);
@ -105,12 +127,15 @@ public class ApexUnitTestClassShouldHaveAssertsRule extends AbstractApexUnitTest
private Pattern getCompiledAdditionalAssertMethodPattern(String additionalAssertMethodPattern) {
if (StringUtils.isNotBlank(additionalAssertMethodPattern)) {
// Check for presence first since we will cache a null value for patterns that don't compile
// Check for presence first since we will cache a null value for patterns that
// don't compile
if (compiledAdditionalAssertMethodPattern == null) {
try {
compiledAdditionalAssertMethodPattern = Optional.of(Pattern.compile(additionalAssertMethodPattern, Pattern.CASE_INSENSITIVE));
compiledAdditionalAssertMethodPattern = Optional
.of(Pattern.compile(additionalAssertMethodPattern, Pattern.CASE_INSENSITIVE));
} catch (IllegalArgumentException e) {
// Cache a null compiled pattern so that we won't try to compile this one again during the run
// Cache a null compiled pattern so that we won't try to compile this one again
// during the run
compiledAdditionalAssertMethodPattern = Optional.ofNullable(null);
throw e;
}

View File

@ -7,13 +7,11 @@ package net.sourceforge.pmd.lang.apex.ast;
import org.junit.Assert;
import org.junit.Test;
import apex.jorje.semantic.ast.compilation.Compilation;
public class ASTFieldTest extends ApexParserTestBase {
@Test
public void testGetType() {
ApexNode<Compilation> node = parse("public class Foo { private String myField = 'a'; }");
ApexNode<?> node = parse("public class Foo { private String myField = 'a'; }");
ASTField field = node.getFirstDescendantOfType(ASTField.class);
Assert.assertEquals("myField", field.getImage());
@ -23,7 +21,7 @@ public class ASTFieldTest extends ApexParserTestBase {
@Test
public void testGetValue() {
ApexNode<Compilation> node = parse("public class Foo { private String myField = 'a'; }");
ApexNode<?> node = parse("public class Foo { private String myField = 'a'; }");
ASTField field = node.getFirstDescendantOfType(ASTField.class);
Assert.assertEquals("a", field.getValue());
@ -31,7 +29,7 @@ public class ASTFieldTest extends ApexParserTestBase {
@Test
public void testGetNoValue() {
ApexNode<Compilation> node = parse("public class Foo { private String myField; }");
ApexNode<?> node = parse("public class Foo { private String myField; }");
ASTField field = node.getFirstDescendantOfType(ASTField.class);
Assert.assertNull(field.getValue());

View File

@ -9,13 +9,11 @@ import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import apex.jorje.semantic.ast.compilation.Compilation;
public class ASTMethodTest extends ApexParserTestBase {
@Test
public void testConstructorName() {
ApexNode<Compilation> node = parse("public class Foo { public Foo() {} public void bar() {} }");
ApexNode<?> node = parse("public class Foo { public Foo() {} public void bar() {} }");
Assert.assertSame(ASTUserClass.class, node.getClass());
List<ASTMethod> methods = node.findChildrenOfType(ASTMethod.class);
Assert.assertEquals("Foo", methods.get(0).getImage()); // constructor

Some files were not shown because too many files have changed in this diff Show More