Merge branch 'java-grammar' into grammar-flatten-body-declarations

This commit is contained in:
Clément Fournier
2020-02-21 14:56:22 +01:00
140 changed files with 2634 additions and 1085 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ bin/
.classpath
.checkstyle
.pmd
.pmdruleset.xml
.ruleset
.settings/
*.iml

View File

@ -18,10 +18,7 @@ First off, thanks for taking the time to contribute!
## Bug reports
We used to use Sourceforge for bug tracking, but we are in the process of moving to github issues.
* Old bugs are still available at <https://sourceforge.net/p/pmd/bugs/>.
* Please report new bugs at <https://github.com/pmd/pmd/issues>.
We use the issue tracker on Github. Please report new bugs at <https://github.com/pmd/pmd/issues>.
When filing a bug report, please provide as much information as possible, so that we can reproduce the issue:
@ -32,7 +29,7 @@ When filing a bug report, please provide as much information as possible, so tha
## Documentation
There is some documentation available under <https://pmd.github.io/pmd>. Feel free to create a bug report if
There is some documentation available under <https://pmd.github.io/latest>. Feel free to create a bug report if
documentation is missing, incomplete or outdated. See [Bug reports](#bug-reports).
The documentation is generated as a Jekyll site, the source is available at: <https://github.com/pmd/pmd/tree/master/docs>. You can find build instructions there.
@ -42,18 +39,18 @@ For more on contributing documentation check <https://pmd.github.io/pmd/pmd_devd
There are various channels, on which you can ask questions:
* The mailing list: [pmd-devel](https://lists.sourceforge.net/lists/listinfo/pmd-devel)
* The discussion forums on sourceforge: <https://sourceforge.net/p/pmd/discussion/>
* On [StackOverflow](https://stackoverflow.com/questions/tagged/pmd): Make sure, to tag your question with "pmd".
* Create a issue for your question at <https://github.com/pmd/pmd/issues>.
* Ask your question on Gitter <https://gitter.im/pmd/pmd>.
## Code Style
PMD uses [checkstyle](http://checkstyle.sourceforge.net/) to enforce a common code style.
See [pmd-checkstyle-config.xml](https://github.com/pmd/build-tools/blob/master/config/src/main/resources/net/sourceforge/pmd/pmd-checkstyle-config.xml) for the configuration and
[the eclipse configuration files](https://github.com/pmd/build-tools/tree/master/config/eclipse) that can
See [pmd-checkstyle-config.xml](https://github.com/pmd/build-tools/blob/master/src/main/resources/net/sourceforge/pmd/pmd-checkstyle-config.xml) for the configuration and
[the eclipse configuration files](https://github.com/pmd/build-tools/tree/master/eclipse) that can
be imported into a fresh workspace.

View File

@ -15,7 +15,16 @@ Additionally it includes **CPD**, the copy-paste-detector. CPD finds duplicated
C/C++, C#, Dart, Fortran, Go, Groovy, Java, JavaScript, JSP, Kotlin, Lua, Matlab, Modelica,
Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex, Scala, Swift and Visualforce.
## Source and Documentation
## Support
* How do I? -- Ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/pmd).
* I got this error, why? -- Ask a question on [StackOverflow](https://stackoverflow.com/questions/tagged/pmd).
* I got this error and I'm sure it's a bug -- file an [issue](https://github.com/pmd/pmd/issues).
* I have an idea/request/question -- file an [issue](https://github.com/pmd/pmd/issues).
* I have a quick question -- ask on our [Gitter chat](https://gitter.im/pmd/pmd).
* Where's your documentation? -- <https://pmd.github.io/latest/>
## Source
Our latest source of PMD can be found on [GitHub](https://github.com/pmd/pmd). Fork us!
@ -26,6 +35,6 @@ The rule designer is developed over at [pmd/pmd-designer](https://github.com/pmd
Please see [its README](https://github.com/pmd/pmd-designer#contributing) for
developer documentation.
## News and Website
## Website
More information can be found on our [Website](https://pmd.github.io) and on [SourceForge](https://sourceforge.net/projects/pmd/).
More information can be found on our [Website](https://pmd.github.io).

View File

@ -52,7 +52,7 @@ public class ApexParser {
ApexRootNode<Compilation> treeRoot = (ApexRootNode) treeBuilder.build(astRoot);
treeRoot.setNoPmdComments(treeBuilder.getSuppressMap());
return treeRoot;
} catch (IOException e) {
} catch (IOException | apex.jorje.services.exception.ParseException e) {
throw new ParseException(e);
}
}

View File

@ -24,6 +24,8 @@ import apex.jorje.semantic.compiler.sfdc.AccessEvaluator;
import apex.jorje.semantic.compiler.sfdc.NoopCompilerProgressCallback;
import apex.jorje.semantic.compiler.sfdc.QueryValidator;
import apex.jorje.semantic.compiler.sfdc.SymbolProvider;
import apex.jorje.services.exception.CompilationException;
import apex.jorje.services.exception.ParseException;
import com.google.common.collect.ImmutableList;
/**
@ -42,14 +44,6 @@ public class CompilerService {
/**
* Configure a compiler with the default configurations:
*
* @param symbolProvider
* EmptySymbolProvider, doesn't provide any symbols that are not
* part of source.
* @param accessEvaluator
* TestAccessEvaluator, doesn't provide any validation.
* @param queryValidator
* TestQueryValidators.Noop, no validation of queries.
*/
CompilerService() {
this(EmptySymbolProvider.get(), new TestAccessEvaluator(), new TestQueryValidators.Noop());
@ -72,14 +66,18 @@ public class CompilerService {
this.queryValidator = queryValidator;
}
/** @throws ParseException If the code is unparsable */
public ApexCompiler visitAstFromString(String source, AstVisitor<AdditionalPassScope> visitor) {
return visitAstsFromStrings(ImmutableList.of(source), visitor, CompilerStage.POST_TYPE_RESOLVE);
}
/** @throws ParseException If the code is unparsable */
public ApexCompiler visitAstsFromStrings(List<String> sources, AstVisitor<AdditionalPassScope> visitor) {
return visitAstsFromStrings(sources, visitor, CompilerStage.POST_TYPE_RESOLVE);
}
/** @throws ParseException If the code is unparsable */
public ApexCompiler visitAstsFromStrings(List<String> sources, AstVisitor<AdditionalPassScope> visitor,
CompilerStage compilerStage) {
List<SourceFile> sourceFiles = sources.stream().map(s -> SourceFile.builder().setBody(s).build())
@ -92,13 +90,32 @@ public class CompilerService {
ApexCompiler compiler = ApexCompiler.builder().setInput(compilationInput).build();
compiler.compile(compilerStage);
callAdditionalPassVisitor(compiler);
throwParseErrorIfAny(compiler);
return compiler;
}
private void throwParseErrorIfAny(ApexCompiler compiler) {
// this ignores semantic errors
ParseException parseError = null;
for (CompilationException error : compiler.getErrors()) {
if (error instanceof ParseException) {
if (parseError == null) {
parseError = (ParseException) error;
} else {
parseError.addSuppressed(error);
}
}
}
if (parseError != null) {
throw parseError;
}
}
private CompilationInput createCompilationInput(List<SourceFile> sourceFiles,
AstVisitor<AdditionalPassScope> visitor) {
AstVisitor<AdditionalPassScope> visitor) {
return new CompilationInput(sourceFiles, symbolProvider, accessEvaluator, queryValidator, visitor,
NoopCompilerProgressCallback.get());
NoopCompilerProgressCallback.get());
}
/**

View File

@ -23,12 +23,7 @@ abstract class AbstractNamingConventionsRule extends AbstractApexRule {
abstract String displayName(String name);
protected void checkMatches(PropertyDescriptor<Pattern> propertyDescriptor, ApexNode<?> node, Object data) {
Pattern regex = getProperty(propertyDescriptor);
String name = node.getImage();
if (!regex.matcher(name).matches()) {
String displayName = displayName(propertyDescriptor.name());
addViolation(data, node, new Object[] { displayName, name, regex.toString() });
}
checkMatches(propertyDescriptor, getProperty(propertyDescriptor), node, data);
}
protected void checkMatches(PropertyDescriptor<Pattern> propertyDescriptor, Pattern overridePattern, ApexNode<?> node, Object data) {

View File

@ -72,7 +72,7 @@ Avoid directly accessing Trigger.old and Trigger.new as it can lead to a bug. Tr
trigger AccountTrigger on Account (before insert, before update) {
Account a = Trigger.new[0]; //Bad: Accessing the trigger array directly is not recommended.
foreach ( Account a : Trigger.new ){
for ( Account a : Trigger.new ){
//Good: Iterate through the trigger.new array instead.
}
}

View File

@ -13,8 +13,8 @@ public class ASTSoqlExpressionTest extends ApexParserTestBase {
@Test
public void testQuery() {
ApexNode<Compilation> node = parse("class Foo { void test1() { Account acc = [SELECT 1 FROM Account]; } }");
ApexNode<Compilation> node = parse("class Foo { void test1() { Account acc = [SELECT col FROM Account]; } }");
ASTSoqlExpression soqlExpression = node.getFirstDescendantOfType(ASTSoqlExpression.class);
Assert.assertEquals("SELECT 1 FROM Account", soqlExpression.getQuery());
Assert.assertEquals("SELECT col FROM Account", soqlExpression.getQuery());
}
}

View File

@ -0,0 +1,17 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.apex.ast;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.ParseException;
public class ApexCompilerTest extends ApexParserTestBase {
@Test(expected = ParseException.class)
public void compileShouldFail() {
apex.parse("public class Foo { private String myField = \"a\"; }");
}
}

View File

@ -44,7 +44,7 @@ public class ApexParserTest extends ApexParserTestBase {
private String testCodeForLineNumbers =
"public class SimpleClass {\n" // line 1
+ " public void method1() {\n" // line 2
+ " System.out.println(\"abc\");\n" // line 3
+ " System.out.println('abc');\n" // line 3
+ " // this is a comment\n" // line 4
+ " }\n" // line 5
+ "}\n"; // line 6

View File

@ -12,10 +12,10 @@ public class ApexParserTestBase {
protected ApexNode<Compilation> parse(String code) {
return (ApexNode<Compilation>) apex.parse(code);
return apex.parse(code);
}
protected ApexNode<Compilation> parseResource(String code) {
return (ApexNode<Compilation>) apex.parseResource(code);
return apex.parseResource(code);
}
}

View File

@ -8,16 +8,17 @@ import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.lang.LanguageVersionHandler;
import net.sourceforge.pmd.lang.apex.ApexLanguageModule;
import net.sourceforge.pmd.lang.apex.multifile.ApexMultifileVisitorFacade;
import net.sourceforge.pmd.lang.ast.RootNode;
import net.sourceforge.pmd.lang.ast.test.BaseParsingHelper;
public class ApexParsingHelper extends BaseParsingHelper<ApexParsingHelper, RootNode> {
import apex.jorje.semantic.ast.compilation.Compilation;
public class ApexParsingHelper extends BaseParsingHelper<ApexParsingHelper, ApexRootNode<Compilation>> {
public static final ApexParsingHelper DEFAULT = new ApexParsingHelper(Params.getDefaultProcess());
private ApexParsingHelper(Params p) {
super(ApexLanguageModule.NAME, RootNode.class, p);
super(ApexLanguageModule.NAME, (Class<ApexRootNode<Compilation>>) (Class) ApexRootNode.class, p);
}
@Override
@ -26,8 +27,8 @@ public class ApexParsingHelper extends BaseParsingHelper<ApexParsingHelper, Root
}
@Override
protected void postProcessing(LanguageVersionHandler handler, LanguageVersion lversion, RootNode rootNode) {
protected void postProcessing(LanguageVersionHandler handler, LanguageVersion lversion, ApexRootNode<Compilation> rootNode) {
super.postProcessing(handler, lversion, rootNode);
new ApexMultifileVisitorFacade().initializeWith((ApexNode<?>) rootNode);
new ApexMultifileVisitorFacade().initializeWith(rootNode);
}
}

View File

@ -85,7 +85,7 @@ public class SomeClass {
if(object1Map.get(object1.Id).Id != null && object1.Text != null){
Item post = new Item();
post.ParentId = object1Map.get(object1.Id).Id;
post.Body = "Something";
post.Body = 'Something';
itemList.add(post);
}
@ -99,7 +99,7 @@ public class SomeClass {
if(object1.Text != null && object1.Id != null){
Item post = new Item();
post.ParentId = object1.Id;
post.Body = "Something";
post.Body = 'Something';
itemList.add(post);
}
}

View File

@ -13,7 +13,7 @@
k++;
} catch (IOException ioe) {
ioe.printStackTrace();
throw new Exception("surprise", ioe);
throw new Exception('surprise', ioe);
} catch (Exception e) {
// do nothing
}
@ -22,7 +22,7 @@
int x = 0, y = 1, z = 2, t = 2;
boolean a = false, b = true, c = false, d = true;
for (String s : list) {
for (String s : lst) { // list is a kw
x++;
}
@ -86,7 +86,7 @@
public Test() {
if (a == 1) {
if (b == 2) {
System.out.println("b");
System.out.println('b');
} else if (b == 1) {
}
} else {

View File

@ -42,8 +42,8 @@ global class Foo {
<expected-problems>1</expected-problems>
<code><![CDATA[
global class Foo {
global interface Bar { {
global interface Bar {
}
}
]]></code>

View File

@ -14,7 +14,7 @@ public class Foo {
@isTest
static void methodATest() {
System.debug('I am a bad debug!'); // not good
System.debug(LoggingLevel.WARN, 'I am a good warning.') // good
System.debug(LoggingLevel.WARN, 'I am a good warning.'); // good
}
}
]]></code>
@ -44,7 +44,7 @@ public class Foo {
public class Foo {
@isTest
static void methodATest() {
System.debug(LoggingLevel.DEBUG, 'I am a good debug.') // good
System.debug(LoggingLevel.DEBUG, 'I am a good debug.'); // good
}
}
]]></code>

View File

@ -9,7 +9,7 @@
<description>class names should not start with lowercase character</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
public class foo {};
public class foo {}
]]></code>
</test-code>
@ -17,7 +17,7 @@ public class foo {};
<description>all is well</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class FooBar {};
public class FooBar {}
]]></code>
</test-code>

View File

@ -34,18 +34,18 @@ public class Foo {
}
]]></code>
</test-code>
<test-code>
<description>#1343 MethodNamingConventions for overrided methods</description>
<description>#1343 MethodNamingConventions for overriden methods</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class MethodNamingConventions implements SomeInterface {
@Override
public void _foo() {}
public override void _foo() {}
}
]]></code>
</test-code>
<test-code>
<description>#25 Method rules should ignore Property Getter/Setter</description>
<expected-problems>0</expected-problems>
@ -84,7 +84,7 @@ public class Foo {
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
void testMethod test_barFoo() {}
testmethod void test_barFoo() {}
}
]]></code>
</test-code>
@ -107,7 +107,7 @@ public class Foo {
<code><![CDATA[
public class Foo {
@isTest
public static void testMethod() { }
public static void testMethod1() { } // "testmethod" is a keyword in apex
public static void staticMethod() { }
public void instanceMethod() { }
}

View File

@ -111,7 +111,7 @@
public Test() {
if (a == 1) {
if (b == 2) {
System.out.println("b");
System.out.println('b');
} else if (b == 1) {
}
} else {
@ -222,7 +222,7 @@
k++;
} catch (IOException ioe) {
ioe.printStackTrace();
throw new Exception("surprise", ioe);
throw new Exception('surprise', ioe);
} catch (Exception e) {
// do nothing
}
@ -233,7 +233,7 @@
k++;
} catch (IOException ioe) {
ioe.printStackTrace();
throw new Exception("surprise", ioe);
throw new Exception('surprise', ioe);
} catch (Exception e) {
// do nothing
}

View File

@ -84,7 +84,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */
@ -92,4 +92,4 @@ public class SomeClass {
}
]]></code>
</test-code>
</test-data>
</test-data>

View File

@ -41,7 +41,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */

View File

@ -106,7 +106,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */

View File

@ -129,7 +129,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */

View File

@ -143,7 +143,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */

View File

@ -119,7 +119,7 @@ public class SomeClass {
* Comment
*/
public void doSomething() {
System.debug("hello world");
System.debug('hello world');
}
/** Field comment */

View File

@ -150,7 +150,7 @@ public class Test {
public Test() {
if (a == 1) {
if (b == 2) {
System.out.println("b");
System.out.println('b');
} else if (b == 1) {
}
} else {

View File

@ -63,33 +63,12 @@ public class Foo {
Integer a5;
Integer a6;
public class Bar {
Integer a7;
Integer a8;
Integer a9;
Integer a10;
Integer a11;
Integer a12;
}
}
]]></code>
</test-code>
<test-code>
<description>outer class, inner interface, both OK</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
Integer a1;
Integer a2;
Integer a3;
Integer a4;
Integer a5;
interface Bar {
static Integer a6;
static Integer a7;
static Integer a8;
static Integer a9;
static Integer a10;
Integer a7;
Integer a8;
Integer a9;
Integer a10;
Integer a11;
Integer a12;
}
}
]]></code>
@ -119,34 +98,22 @@ public class Foo {
Integer b16;
}
public class Bar2 {
Integer b1;
Integer b2;
Integer b3;
Integer b4;
Integer b5;
Integer b6;
Integer b7;
Integer b8;
Integer b9;
Integer b10;
Integer b11;
Integer b12;
Integer b13;
Integer b14;
Integer b15;
Integer b16;
}
}
]]></code>
</test-code>
<test-code>
<description>anonymous class with a field</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
public class Foo {
public class Bar1 {
Object foo = new Object() {public Integer x;};
Integer b1;
Integer b2;
Integer b3;
Integer b4;
Integer b5;
Integer b6;
Integer b7;
Integer b8;
Integer b9;
Integer b10;
Integer b11;
Integer b12;
Integer b13;
Integer b14;
Integer b15;
Integer b16;
}
}
]]></code>

View File

@ -20,9 +20,9 @@ trigger AccountTrigger on Account (before insert, before update) {
<expected-problems>0</expected-problems>
<code><![CDATA[
trigger AccountTrigger on Account (before insert, before update) {
foreach ( Account a : Trigger.new ){
for ( Account a : Trigger.new ){
//Good: Iterate through the trigger.new array instead.
system.debug(a);
System.debug(a);
}
}
]]></code>
@ -40,5 +40,5 @@ class NotATrigger {
]]></code>
</test-code>
</test-data>

View File

@ -607,7 +607,8 @@ public class Foo {
}
public void doChecks() {
if (!Contact.sObjectType.getDescribe().isCreateable() && !Contact.sObjectType.getDescribe().isUpdateable()) {
if (!Contact.sObjectType.getDescribe().isCreateable()
&& !Contact.sObjectType.getDescribe().isUpdateable()) {
throw new NoAccessException();
}
}
@ -626,7 +627,7 @@ public class Foo {
}
public void doChecks() {
anotherLevelHere("yolo");
anotherLevelHere('yolo');
}
private void anotherLevelHere(String s) {

View File

@ -274,11 +274,11 @@ public class Foo {
<test-code>
<description>Integer is safe in query</description>
<expected-problems>0</expected-problems>
<code><![CDATA[
<code><![CDATA[
public class Foo {
public void test1(String objName, String limit) {
Integer nLimit = Integer.valueOf(limit);
List<SObject> res = Database.query('Select Id, Name From ' + String.escapeSingleQuotes(objName) + ' LIMIT ' + nLimit);
public void test1(String objName, String lim) { // "limit" is a kw
Integer nLimit = Integer.valueOf(lim);
List<SObject> res = Database.query('Select Id, Name From ' + String.escapeSingleQuotes(objName) + ' LIMIT ' + nLimit);
}
}
]]></code>
@ -316,10 +316,10 @@ public class Foo {
isn't
</description>
<expected-problems>1</expected-problems>
<code><![CDATA[
<code><![CDATA[
public class Foo {
public void test1(String name) {
List<SObject> res = Database.query('Select Id,Name From ' + (name == 'Account' ? name : 'Cases');
List<SObject> res = Database.query('Select Id,Name From ' + (name == 'Account' ? name : 'Cases'));
}
}
]]></code>

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