From 61b1c372cd9e633c0a7ba86f39ab6e8fa2df95db Mon Sep 17 00:00:00 2001 From: Willem Hajenius Date: Mon, 21 Oct 2024 23:45:20 +0200 Subject: [PATCH 01/17] [apex] Must use case-insensitive input stream to avoid choking on Unicode escape sequences --- .../pmd/lang/apex/ast/ApexCommentBuilder.java | 4 ++- .../pmd/lang/apex/ast/ApexLexerTest.java | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java index a135ca4603..48d41f0faa 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java @@ -22,6 +22,7 @@ import net.sourceforge.pmd.lang.document.TextDocument; import net.sourceforge.pmd.lang.document.TextRegion; import io.github.apexdevtools.apexparser.ApexLexer; +import io.github.apexdevtools.apexparser.CaseInsensitiveInputStream; @InternalApi final class ApexCommentBuilder { @@ -103,7 +104,8 @@ final class ApexCommentBuilder { } private static CommentInformation extractInformationFromComments(TextDocument sourceCode, String suppressMarker) { - ApexLexer lexer = new ApexLexer(CharStreams.fromString(sourceCode.getText().toString())); + String source = sourceCode.getText().toString(); + ApexLexer lexer = new ApexLexer(new CaseInsensitiveInputStream(CharStreams.fromString(source))); List allCommentTokens = new ArrayList<>(); Map suppressMap = new HashMap<>(); diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java index 67c6706f29..b075160370 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java @@ -8,14 +8,18 @@ package net.sourceforge.pmd.lang.apex.ast; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.Token; import org.junit.jupiter.api.Test; import io.github.apexdevtools.apexparser.ApexLexer; import io.github.apexdevtools.apexparser.ApexParser; +import io.github.apexdevtools.apexparser.CaseInsensitiveInputStream; /** * This is an exploration test for {@link ApexLexer}. @@ -49,4 +53,35 @@ class ApexLexerTest { ApexParser.CompilationUnitContext compilationUnit = parser.compilationUnit(); assertNotNull(compilationUnit); } + + @Test + void testLexerUnicodeEscapes() { + String s = "'Fran\\u00E7ois'"; + assertEquals(2, getLexingErrors(CharStreams.fromString(s))); + assertEquals(0, getLexingErrors(new CaseInsensitiveInputStream(CharStreams.fromString(s)))); + } + + private int getLexingErrors(CharStream stream) { + ApexLexer lexer = new ApexLexer(stream); + ErrorListener errorListener = new ErrorListener(); + lexer.removeErrorListeners(); // Avoid distracting "token recognition error" stderr output + lexer.addErrorListener(errorListener); + CommonTokenStream tokens = new CommonTokenStream(lexer); + tokens.fill(); + return errorListener.getErrorCount(); + } + + static class ErrorListener extends BaseErrorListener { + private int errorCount = 0; + + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, + int charPositionInLine, String msg, RecognitionException e) { + ++errorCount; + } + + public int getErrorCount() { + return errorCount; + } + } } From 07de5559bcb39ab3e4908735d16c4954f005596e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 03:35:46 +0000 Subject: [PATCH 02/17] Bump org.apache.commons:commons-compress from 1.26.0 to 1.27.1 Bumps org.apache.commons:commons-compress from 1.26.0 to 1.27.1. --- updated-dependencies: - dependency-name: org.apache.commons:commons-compress dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pmd-dist/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-dist/pom.xml b/pmd-dist/pom.xml index 7bfaf114e5..5a40e514e2 100644 --- a/pmd-dist/pom.xml +++ b/pmd-dist/pom.xml @@ -178,7 +178,7 @@ org.apache.commons commons-compress - 1.26.0 + 1.27.1 test From 529693c916ebca6226ae501c1ceaf53eb88f95ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Wed, 13 Nov 2024 22:27:51 +0100 Subject: [PATCH 03/17] [java] fix inference dependency issue Reported in #5324 I improved the verbose logging output a bit so some of the changes are not directly relevant. --- .../types/internal/infer/ExprCheckHelper.java | 18 +- .../lang/java/types/internal/infer/Infer.java | 13 +- .../internal/infer/InferenceContext.java | 87 +++++++- .../internal/infer/TypeInferenceLogger.java | 74 +++++-- .../types/internal/infer/VarWalkStrategy.java | 8 + .../lang/java/types/TypesTreeDumpTest.java | 5 + .../bestpractices/xml/UnusedPrivateMethod.xml | 43 ++++ .../NestedLambdasAndMethodCalls.java | 38 ++++ .../dumptests/NestedLambdasAndMethodCalls.txt | 194 ++++++++++++++++++ .../java/types/dumptests/UnnamedPatterns.txt | 6 +- 10 files changed, 448 insertions(+), 38 deletions(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.txt diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java index c5c20caec9..dc8955fcb0 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java @@ -552,8 +552,15 @@ final class ExprCheckHelper { // finally, add bounds if (result != ts.NO_TYPE) { + Set inputIvars = infCtx.freeVarsIn(groundFun.getFormalParameters()); + // The free vars of the return type depend on the free vars of the parameters. + // This explicit dependency is there to prevent solving the variables in the + // return type before solving those of the parameters. That is because the variables + // mentioned in the return type may be further constrained by adding the return constraints + // below (in the listener), which is only triggered when the input ivars have been instantiated. + infCtx.addInstantiationDependencies(infCtx.freeVarsIn(groundFun.getReturnType()), inputIvars); infCtx.addInstantiationListener( - infCtx.freeVarsIn(groundFun.getFormalParameters()), + inputIvars, solvedCtx -> { if (mayMutateExpr()) { lambda.setInferredType(solvedCtx.ground(groundTargetType)); @@ -562,8 +569,15 @@ final class ExprCheckHelper { lambda.updateTypingContext(solvedGroundFun); } JTypeMirror groundResult = solvedCtx.ground(result); + // We need to build another checker that uses the solved context. + // This is because the free vars may have been adopted by a parent + // context, so the solvedCtx may be that parent context. The checks + // must use that context so that constraints and listeners are added + // to the parent context, since that one is responsible for solving + // the variables. + ExprCheckHelper newChecker = new ExprCheckHelper(solvedCtx, phase, this.checker, site, infer); for (ExprMirror expr : lambda.getResultExpressions()) { - if (!isCompatible(groundResult, expr)) { + if (!newChecker.isCompatible(groundResult, expr)) { return; } } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/Infer.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/Infer.java index 02f16611d5..7982304210 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/Infer.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/Infer.java @@ -602,17 +602,20 @@ public final class Infer { // see: https://docs.oracle.com/javase/specs/jls/se9/html/jls-18.html#jls-18.5.1 // as per https://docs.oracle.com/javase/specs/jls/se9/html/jls-18.html#jls-18.5.2 // we only test it can reduce, we don't commit inferred types at this stage - InferenceContext ctxCopy = infCtx.copy(); - LOG.applicabilityTest(ctxCopy, m); - ctxCopy.solve(/*onlyBoundedVars:*/isPreJava8()); - + InferenceContext ctxCopy = infCtx.shallowCopy(); + LOG.applicabilityTest(ctxCopy); + try { + ctxCopy.solve(/*onlyBoundedVars:*/isPreJava8()); + } finally { + LOG.finishApplicabilityTest(); + } // if unchecked conversion was needed, update the site for invocation pass if (ctxCopy.needsUncheckedConversion()) { site.setNeedsUncheckedConversion(); } // don't commit any types - return m; + return infCtx.mapToIVars(m); } } finally { // Note that even if solve succeeded, listeners checking deferred diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java index ba3a78640e..73b843439f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java @@ -13,11 +13,13 @@ import java.util.Collection; import java.util.Collections; import java.util.Deque; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.function.Supplier; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -38,6 +40,7 @@ import net.sourceforge.pmd.lang.java.types.internal.infer.IncorporationAction.Pr import net.sourceforge.pmd.lang.java.types.internal.infer.IncorporationAction.SubstituteInst; import net.sourceforge.pmd.lang.java.types.internal.infer.InferenceVar.BoundKind; import net.sourceforge.pmd.lang.java.types.internal.infer.VarWalkStrategy.GraphWalk; +import net.sourceforge.pmd.util.CollectionUtil; /** * Context of a type inference process. This object maintains a set of @@ -51,6 +54,13 @@ final class InferenceContext { private static int ctxId = 0; private final Map> instantiationListeners = new HashMap<>(); + // explicit dependencies between variables for graph building + private final Map> instantiationConstraints = new HashMap<>(); + // This flag is set to true when the explicit dependencies are changed, + // or when this context adopted new ivars. This means we should interrupt + // resolution and recompute the dependency graph between ivars, because + // the new variables may have dependencies on existing variables, and vice versa. + private boolean graphWasChanged = false; private final Set freeVars = new LinkedHashSet<>(); private final Set inferenceVars = new LinkedHashSet<>(); @@ -127,18 +137,19 @@ final class InferenceContext { } } - public InferenceContext copy() { + /** + * Performs a shallow copy of this context, which would allow solving + * the variables without executing listeners. Instantiation listeners + * are not copied, and parent contexts are not copied. + */ + public InferenceContext shallowCopy() { final InferenceContext copy = new InferenceContext(ts, supertypeCheckCache, Collections.emptyList(), logger); copy.freeVars.addAll(this.freeVars); copy.inferenceVars.addAll(this.inferenceVars); copy.incorporationActions.addAll(this.incorporationActions); + copy.instantiationConstraints.putAll(this.instantiationConstraints); copy.mapping = mapping; // mapping is immutable, so we can share it safely - // recursively copy parents… - if (this.parent != null) { - copy.parent = this.parent.copy(); - } - return copy; } @@ -310,10 +321,20 @@ final class InferenceContext { * Copy variable in this inference context to the given context */ void duplicateInto(final InferenceContext that) { + boolean changedGraph = !that.freeVars.containsAll(this.freeVars) + || !this.instantiationConstraints.isEmpty(); + that.graphWasChanged |= changedGraph; that.inferenceVars.addAll(this.inferenceVars); that.freeVars.addAll(this.freeVars); that.incorporationActions.addAll(this.incorporationActions); that.instantiationListeners.putAll(this.instantiationListeners); + CollectionUtil.mergeMaps( + that.instantiationConstraints, + this.instantiationConstraints, + (set1, set2) -> { + set1.addAll(set2); + return set1; + }); this.parent = that; @@ -324,6 +345,30 @@ final class InferenceContext { } + // The `from` ivars depend on the `dependencies` ivars for resolution. + void addInstantiationDependencies(Set from, Set dependencies) { + if (from.isEmpty()) { + return; + } + Set outputVars = new HashSet<>(dependencies); + outputVars.removeAll(from); + if (outputVars.isEmpty()) { + return; + } + for (InferenceVar inputVar : from) { + logger.ivarDependencyRegistered(this, inputVar, outputVars); + instantiationConstraints.merge(inputVar, outputVars, (o1, o2) -> { + o2 = new LinkedHashSet<>(o2); + o2.addAll(o1); + return o2; + }); + } + } + + Map> getInstantiationDependencies() { + return instantiationConstraints; + } + void addInstantiationListener(Set relevantTypes, InstantiationListener listener) { Set free = freeVarsIn(relevantTypes); if (free.isEmpty()) { @@ -448,7 +493,7 @@ final class InferenceContext { } boolean solve(boolean onlyBoundedVars) { - return solve(new GraphWalk(this, onlyBoundedVars)); + return solve(() -> new GraphWalk(this, onlyBoundedVars)); } /** @@ -459,6 +504,26 @@ final class InferenceContext { solve(new GraphWalk(var)); } + + private boolean solve(Supplier newWalker) { + VarWalkStrategy strategy = newWalker.get(); + while (strategy != null) { + if (solve(strategy)) { + break; + } + strategy = newWalker.get(); + } + return freeVars.isEmpty(); + } + + + /** + * This returns true if solving the VarWalkStrategy succeeded entirely. + * Resolution can be interrupted early to account for new ivars and dependencies, + * which may change the graph dependencies. In this case this method returns + * false, we recompute the graph with the new ivars and dependencies, and + * we try again to make progress. + */ private boolean solve(VarWalkStrategy walker) { incorporate(); @@ -470,6 +535,12 @@ final class InferenceContext { //repeat until all variables are solved outer: while (!intersect(freeVars, varsToSolve).isEmpty() && progress) { + if (graphWasChanged) { + graphWasChanged = false; + logger.contextDependenciesChanged(this); + return false; + } + progress = false; for (List wave : ReductionStep.WAVES) { if (solveBatchProgressed(varsToSolve, wave)) { @@ -481,7 +552,7 @@ final class InferenceContext { } } } - return freeVars.isEmpty(); + return true; } /** diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java index 023e422a49..2c9cfff9ef 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java @@ -12,6 +12,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -61,7 +62,10 @@ public interface TypeInferenceLogger { default void ctxInitialization(InferenceContext ctx, JMethodSig sig) { } - default void applicabilityTest(InferenceContext ctx, JMethodSig sig) { } + default void applicabilityTest(InferenceContext ctx) { } + + default void finishApplicabilityTest() { + } default void startArgsChecks() { } @@ -81,6 +85,8 @@ public interface TypeInferenceLogger { default void propagateAndAbort(InferenceContext context, InferenceContext parent) { } + default void contextDependenciesChanged(InferenceContext ctx) { } + // ivar events @@ -90,6 +96,8 @@ public interface TypeInferenceLogger { default void ivarInstantiated(InferenceContext ctx, InferenceVar var, JTypeMirror inst) { } + default void ivarDependencyRegistered(InferenceContext ctx, InferenceVar var, Set deps) { } + /** * Log that the instantiation of the method type m for the given @@ -136,9 +144,11 @@ public interface TypeInferenceLogger { protected final PrintStream out; - protected static final int LEVEL_INCREMENT = 4; - private int level; private String indent; + /** + * Four spaces. + */ + protected static final String BASE_INDENT = " "; protected static final String ANSI_RESET = "\u001B[0m"; protected static final String ANSI_BLUE = "\u001B[34m"; @@ -177,16 +187,24 @@ public interface TypeInferenceLogger { public SimpleLogger(PrintStream out) { this.out = out; - updateLevel(0); + this.indent = ""; } - protected int getLevel() { - return level; + protected void addIndentSegment(String segment) { + indent += segment; } - protected void updateLevel(int increment) { - level += increment; - indent = StringUtils.repeat(' ', level); + protected void removeIndentSegment(String segment) { + assert indent.endsWith(segment) : "mismatched end section!"; + indent = StringUtils.removeEnd(indent, segment); + } + + protected void setIndent(String indent) { + this.indent = indent; + } + + protected String getIndent() { + return indent; } protected void println(String str) { @@ -196,13 +214,13 @@ public interface TypeInferenceLogger { protected void endSection(String footer) { - updateLevel(-LEVEL_INCREMENT); + removeIndentSegment(BASE_INDENT); println(footer); } protected void startSection(String header) { println(header); - updateLevel(+LEVEL_INCREMENT); + addIndentSegment(BASE_INDENT); } @Override @@ -335,7 +353,7 @@ public interface TypeInferenceLogger { class VerboseLogger extends SimpleLogger { - private final Deque marks = new ArrayDeque<>(); + private final Deque marks = new ArrayDeque<>(); public VerboseLogger(PrintStream out) { super(out); @@ -343,16 +361,16 @@ public interface TypeInferenceLogger { } void mark() { - marks.push(getLevel()); + marks.push(getIndent()); } void rollback(String lastWords) { - int pop = marks.pop(); - updateLevel(pop - getLevel()); // back to normal + final String savedIndent = marks.pop(); + setIndent(savedIndent); // back to normal if (!lastWords.isEmpty()) { - updateLevel(+LEVEL_INCREMENT); + addIndentSegment(BASE_INDENT); println(lastWords); - updateLevel(-LEVEL_INCREMENT); + setIndent(savedIndent); } } @@ -369,8 +387,14 @@ public interface TypeInferenceLogger { } @Override - public void applicabilityTest(InferenceContext ctx, JMethodSig sig) { - println(String.format("Applicability testing with Context %-11d%s", ctx.getId(), ppHighlight(ctx.mapToIVars(sig)))); + public void applicabilityTest(InferenceContext ctx) { + println(String.format("Solving with context %d for applicability testing", ctx.getId())); + addIndentSegment("| "); + } + + @Override + public void finishApplicabilityTest() { + removeIndentSegment("| "); } @Override @@ -404,7 +428,7 @@ public interface TypeInferenceLogger { @Override public void startArg(int i, ExprMirror expr, JTypeMirror formalType) { - startSection("Checking arg " + i + " against " + formalType); + startSection("Checking arg " + i + " against " + colorIvars(formalType)); printExpr(expr); } @@ -452,6 +476,16 @@ public interface TypeInferenceLogger { println(addCtxInfo(ctx, "Ivar instantiated") + color(var + " := ", ANSI_BLUE) + colorIvars(inst)); } + @Override + public void ivarDependencyRegistered(InferenceContext ctx, InferenceVar var, Set deps) { + println(addCtxInfo(ctx, "Ivar dependency registered: ") + color(var + " -> ", ANSI_BLUE) + colorIvars(deps)); + } + + @Override + public void contextDependenciesChanged(InferenceContext ctx) { + println("Recomputing dependency graph (ctx " + ctx.getId() + ")"); + } + private @NonNull String addCtxInfo(InferenceContext ctx, String event) { return String.format("%-20s(ctx %d): ", event, ctx.getId()); } diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/VarWalkStrategy.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/VarWalkStrategy.java index 2177a1cf92..19774ca49e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/VarWalkStrategy.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/VarWalkStrategy.java @@ -90,6 +90,14 @@ interface VarWalkStrategy extends Iterator> { } } + ctx.getInstantiationDependencies().forEach((ivar, deps) -> { + Vertex vertex = graph.addLeaf(ivar); + for (InferenceVar dep : deps) { + Vertex target = graph.addLeaf(dep); + graph.addEdge(vertex, target); + } + }); + // Here, "α depends on β" is modelled by an edge α -> β // Merge strongly connected components into a "super node". diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java index f69b79479c..9b8baaeca6 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java @@ -50,6 +50,11 @@ class TypesTreeDumpTest extends BaseTreeDumpTest { doTest("UnnamedPatterns"); } + @Test + void testNestedLambdasAndMethodCalls() { + doTest("NestedLambdasAndMethodCalls"); + } + @Override protected @NonNull String normalize(@NonNull String str) { return super.normalize(str) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml index e81d963fcb..2679f0a8c5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml @@ -2134,4 +2134,47 @@ public class ObtainViaTest { } ]]> + + UnusedPrivateMethod with method reference + 0 + > map = new Main().run(library); + System.out.println(map); + } + + private Map> run(Library library) { + return library + .books() + .stream() + .map(book -> book.lenders().stream().collect(Collectors.toMap(Lender::name, lender -> Map.of(book.title(), lender.status())))) + .reduce(this::reduceBooksAndLenderStatusByLender) + .orElse(null); + } + + private Map> reduceBooksAndLenderStatusByLender( + Map> previousMap, + Map> nextMap + ) { + previousMap.putAll(nextMap); + return previousMap; + } + } + + + record Lender(String name, String status) {} + record Book(String title, Collection lenders) {} + record Library(Collection books) {} + ]]> + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.java new file mode 100644 index 0000000000..33914e0a68 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.java @@ -0,0 +1,38 @@ +package org.example.unusedPrivateMethod; + +import static java.util.Collections.emptySet; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +public class NestedLambdasAndMethodCalls { + + public static void main(String[] args) { + Library library = new Library(emptySet()); + Map> map = new Main().run(library); + System.out.println(map); + } + + private Map> run(Library library) { + return library + .books() + .stream() + .map(book -> book.lenders().stream().collect(Collectors.toMap(Lender::name, lender -> Map.of(book.title(), lender.status())))) + .reduce(this::reduceBooksAndLenderStatusByLender) + .orElse(null); + } + + private Map> reduceBooksAndLenderStatusByLender( + Map> previousMap, + Map> nextMap + ) { + previousMap.putAll(nextMap); + return previousMap; + } +} + + +record Lender(String name, String status) {} +record Book(String title, Collection lenders) {} +record Library(Collection books) {} \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.txt new file mode 100644 index 0000000000..9099296ff8 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/NestedLambdasAndMethodCalls.txt @@ -0,0 +1,194 @@ ++- CompilationUnit[] + +- PackageDeclaration[] + | +- ModifierList[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ClassDeclaration[@TypeMirror = "org.example.unusedPrivateMethod.NestedLambdasAndMethodCalls"] + | +- ModifierList[] + | +- ClassBody[] + | +- MethodDeclaration[@Name = "main"] + | | +- ModifierList[] + | | +- VoidType[@TypeMirror = "void"] + | | +- FormalParameters[] + | | | +- FormalParameter[@TypeMirror = "java.lang.String[]"] + | | | +- ModifierList[] + | | | +- ArrayType[@TypeMirror = "java.lang.String[]"] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | | +- ArrayDimensions[] + | | | | +- ArrayTypeDim[] + | | | +- VariableId[@Name = "args", @TypeMirror = "java.lang.String[]"] + | | +- Block[] + | | +- LocalVariableDeclaration[] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | +- VariableDeclarator[] + | | | +- VariableId[@Name = "library", @TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | +- ConstructorCall[@Failed = false, @Function = "org.example.unusedPrivateMethod.Library.new(java.util.Collection) -> org.example.unusedPrivateMethod.Library", @MethodName = "new", @TypeMirror = "org.example.unusedPrivateMethod.Library", @Unchecked = false, @VarargsCall = false] + | | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | +- ArgumentList[] + | | | +- MethodCall[@Failed = false, @Function = "java.util.Collections. emptySet() -> java.util.Set", @MethodName = "emptySet", @TypeMirror = "java.util.Set", @Unchecked = false, @VarargsCall = false] + | | | +- ArgumentList[] + | | +- LocalVariableDeclaration[] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "java.util.Map>"] + | | | | +- TypeArguments[] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | | +- ClassType[@TypeMirror = "java.util.Map"] + | | | | +- TypeArguments[] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- VariableDeclarator[] + | | | +- VariableId[@Name = "map", @TypeMirror = "java.util.Map>"] + | | | +- MethodCall[@Failed = true, @Function = "(*unknown*).(*unknown method*)() -> (*unknown*)", @MethodName = "run", @TypeMirror = "(*unknown*)", @Unchecked = false, @VarargsCall = false] + | | | +- ConstructorCall[@Failed = true, @Function = "(*unknown*).(*unknown method*)() -> (*unknown*)", @MethodName = "new", @TypeMirror = "*Main", @Unchecked = false, @VarargsCall = false] + | | | | +- ClassType[@TypeMirror = "*Main"] + | | | | +- ArgumentList[] + | | | +- ArgumentList[] + | | | +- VariableAccess[@Name = "library", @TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | +- ExpressionStatement[] + | | +- MethodCall[@Failed = false, @Function = "java.io.PrintStream.println(java.lang.Object) -> void", @MethodName = "println", @TypeMirror = "void", @Unchecked = false, @VarargsCall = false] + | | +- FieldAccess[@Name = "out", @TypeMirror = "java.io.PrintStream"] + | | | +- TypeExpression[@TypeMirror = "java.lang.System"] + | | | +- ClassType[@TypeMirror = "java.lang.System"] + | | +- ArgumentList[] + | | +- VariableAccess[@Name = "map", @TypeMirror = "java.util.Map>"] + | +- MethodDeclaration[@Name = "run"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.util.Map>"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- ClassType[@TypeMirror = "java.util.Map"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | +- FormalParameters[] + | | | +- FormalParameter[@TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | +- VariableId[@Name = "library", @TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | +- Block[] + | | +- ReturnStatement[] + | | +- MethodCall[@Failed = false, @Function = "java.util.Optional>>.orElse(java.util.Map>) -> java.util.Map>", @MethodName = "orElse", @TypeMirror = "java.util.Map>", @Unchecked = false, @VarargsCall = false] + | | +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream>>.reduce(java.util.function.BinaryOperator>>) -> java.util.Optional>>", @MethodName = "reduce", @TypeMirror = "java.util.Optional>>", @Unchecked = false, @VarargsCall = false] + | | | +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream. map(java.util.function.Function>>) -> java.util.stream.Stream>>", @MethodName = "map", @TypeMirror = "java.util.stream.Stream>>", @Unchecked = false, @VarargsCall = false] + | | | | +- MethodCall[@Failed = false, @Function = "java.util.Collection.stream() -> java.util.stream.Stream", @MethodName = "stream", @TypeMirror = "java.util.stream.Stream", @Unchecked = false, @VarargsCall = false] + | | | | | +- MethodCall[@Failed = false, @Function = "org.example.unusedPrivateMethod.Library.books() -> java.util.Collection", @MethodName = "books", @TypeMirror = "java.util.Collection", @Unchecked = false, @VarargsCall = false] + | | | | | | +- VariableAccess[@Name = "library", @TypeMirror = "org.example.unusedPrivateMethod.Library"] + | | | | | | +- ArgumentList[] + | | | | | +- ArgumentList[] + | | | | +- ArgumentList[] + | | | | +- LambdaExpression[@TypeMirror = "java.util.function.Function>>"] + | | | | +- LambdaParameterList[] + | | | | | +- LambdaParameter[@TypeMirror = "org.example.unusedPrivateMethod.Book"] + | | | | | +- ModifierList[] + | | | | | +- VariableId[@Name = "book", @TypeMirror = "org.example.unusedPrivateMethod.Book"] + | | | | +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream. collect(java.util.stream.Collector>>) -> java.util.Map>", @MethodName = "collect", @TypeMirror = "java.util.Map>", @Unchecked = false, @VarargsCall = false] + | | | | +- MethodCall[@Failed = false, @Function = "java.util.Collection.stream() -> java.util.stream.Stream", @MethodName = "stream", @TypeMirror = "java.util.stream.Stream", @Unchecked = false, @VarargsCall = false] + | | | | | +- MethodCall[@Failed = false, @Function = "org.example.unusedPrivateMethod.Book.lenders() -> java.util.Collection", @MethodName = "lenders", @TypeMirror = "java.util.Collection", @Unchecked = false, @VarargsCall = false] + | | | | | | +- VariableAccess[@Name = "book", @TypeMirror = "org.example.unusedPrivateMethod.Book"] + | | | | | | +- ArgumentList[] + | | | | | +- ArgumentList[] + | | | | +- ArgumentList[] + | | | | +- MethodCall[@Failed = false, @Function = "java.util.stream.Collectors. toMap(java.util.function.Function, java.util.function.Function>) -> java.util.stream.Collector>>", @MethodName = "toMap", @TypeMirror = "java.util.stream.Collector>>", @Unchecked = false, @VarargsCall = false] + | | | | +- TypeExpression[@TypeMirror = "java.util.stream.Collectors"] + | | | | | +- ClassType[@TypeMirror = "java.util.stream.Collectors"] + | | | | +- ArgumentList[] + | | | | +- MethodReference[@TypeMirror = "java.util.function.Function"] + | | | | | +- TypeExpression[@TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | | | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | | | +- LambdaExpression[@TypeMirror = "java.util.function.Function>"] + | | | | +- LambdaParameterList[] + | | | | | +- LambdaParameter[@TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | | | | +- ModifierList[] + | | | | | +- VariableId[@Name = "lender", @TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | | | +- MethodCall[@Failed = false, @Function = "java.util.Map. of(java.lang.String, java.lang.String) -> java.util.Map", @MethodName = "of", @TypeMirror = "java.util.Map", @Unchecked = false, @VarargsCall = false] + | | | | +- TypeExpression[@TypeMirror = "java.util.Map"] + | | | | | +- ClassType[@TypeMirror = "java.util.Map"] + | | | | +- ArgumentList[] + | | | | +- MethodCall[@Failed = false, @Function = "org.example.unusedPrivateMethod.Book.title() -> java.lang.String", @MethodName = "title", @TypeMirror = "java.lang.String", @Unchecked = false, @VarargsCall = false] + | | | | | +- VariableAccess[@Name = "book", @TypeMirror = "org.example.unusedPrivateMethod.Book"] + | | | | | +- ArgumentList[] + | | | | +- MethodCall[@Failed = false, @Function = "org.example.unusedPrivateMethod.Lender.status() -> java.lang.String", @MethodName = "status", @TypeMirror = "java.lang.String", @Unchecked = false, @VarargsCall = false] + | | | | +- VariableAccess[@Name = "lender", @TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | | | +- ArgumentList[] + | | | +- ArgumentList[] + | | | +- MethodReference[@TypeMirror = "java.util.function.BinaryOperator>>"] + | | | +- ThisExpression[@TypeMirror = "org.example.unusedPrivateMethod.NestedLambdasAndMethodCalls"] + | | +- ArgumentList[] + | | +- NullLiteral[@TypeMirror = "null"] + | +- MethodDeclaration[@Name = "reduceBooksAndLenderStatusByLender"] + | +- ModifierList[] + | +- ClassType[@TypeMirror = "java.util.Map>"] + | | +- TypeArguments[] + | | +- ClassType[@TypeMirror = "java.lang.String"] + | | +- ClassType[@TypeMirror = "java.util.Map"] + | | +- TypeArguments[] + | | +- ClassType[@TypeMirror = "java.lang.String"] + | | +- ClassType[@TypeMirror = "java.lang.String"] + | +- FormalParameters[] + | | +- FormalParameter[@TypeMirror = "java.util.Map>"] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "java.util.Map>"] + | | | | +- TypeArguments[] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | | +- ClassType[@TypeMirror = "java.util.Map"] + | | | | +- TypeArguments[] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- VariableId[@Name = "previousMap", @TypeMirror = "java.util.Map>"] + | | +- FormalParameter[@TypeMirror = "java.util.Map>"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.util.Map>"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- ClassType[@TypeMirror = "java.util.Map"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | +- VariableId[@Name = "nextMap", @TypeMirror = "java.util.Map>"] + | +- Block[] + | +- ExpressionStatement[] + | | +- MethodCall[@Failed = false, @Function = "java.util.Map>.putAll(java.util.Map>) -> void", @MethodName = "putAll", @TypeMirror = "void", @Unchecked = false, @VarargsCall = false] + | | +- VariableAccess[@Name = "previousMap", @TypeMirror = "java.util.Map>"] + | | +- ArgumentList[] + | | +- VariableAccess[@Name = "nextMap", @TypeMirror = "java.util.Map>"] + | +- ReturnStatement[] + | +- VariableAccess[@Name = "previousMap", @TypeMirror = "java.util.Map>"] + +- RecordDeclaration[@TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | +- ModifierList[] + | +- RecordComponentList[] + | | +- RecordComponent[@TypeMirror = "java.lang.String"] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- VariableId[@Name = "name", @TypeMirror = "java.lang.String"] + | | +- RecordComponent[@TypeMirror = "java.lang.String"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.lang.String"] + | | +- VariableId[@Name = "status", @TypeMirror = "java.lang.String"] + | +- RecordBody[] + +- RecordDeclaration[@TypeMirror = "org.example.unusedPrivateMethod.Book"] + | +- ModifierList[] + | +- RecordComponentList[] + | | +- RecordComponent[@TypeMirror = "java.lang.String"] + | | | +- ModifierList[] + | | | +- ClassType[@TypeMirror = "java.lang.String"] + | | | +- VariableId[@Name = "title", @TypeMirror = "java.lang.String"] + | | +- RecordComponent[@TypeMirror = "java.util.Collection"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.util.Collection"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Lender"] + | | +- VariableId[@Name = "lenders", @TypeMirror = "java.util.Collection"] + | +- RecordBody[] + +- RecordDeclaration[@TypeMirror = "org.example.unusedPrivateMethod.Library"] + +- ModifierList[] + +- RecordComponentList[] + | +- RecordComponent[@TypeMirror = "java.util.Collection"] + | +- ModifierList[] + | +- ClassType[@TypeMirror = "java.util.Collection"] + | | +- TypeArguments[] + | | +- ClassType[@TypeMirror = "org.example.unusedPrivateMethod.Book"] + | +- VariableId[@Name = "books", @TypeMirror = "java.util.Collection"] + +- RecordBody[] diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnnamedPatterns.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnnamedPatterns.txt index 25eb7dd0d7..e1fa78ded1 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnnamedPatterns.txt +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnnamedPatterns.txt @@ -583,7 +583,7 @@ | +- ArgumentList[] | +- StringLiteral[@TypeMirror = "java.lang.String"] +- ExpressionStatement[] - +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream. collect(java.util.stream.Collector>) -> java.util.Map", @MethodName = "collect", @TypeMirror = "java.util.Map", @Unchecked = false, @VarargsCall = false] + +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream. collect(java.util.stream.Collector>) -> java.util.Map", @MethodName = "collect", @TypeMirror = "java.util.Map", @Unchecked = false, @VarargsCall = false] +- MethodCall[@Failed = false, @Function = "java.util.Collection.stream() -> java.util.stream.Stream", @MethodName = "stream", @TypeMirror = "java.util.stream.Stream", @Unchecked = false, @VarargsCall = false] | +- MethodCall[@Failed = false, @Function = "java.util.List. of(java.lang.String, java.lang.String) -> java.util.List", @MethodName = "of", @TypeMirror = "java.util.List", @Unchecked = false, @VarargsCall = false] | | +- TypeExpression[@TypeMirror = "java.util.List"] @@ -593,14 +593,14 @@ | | +- StringLiteral[@TypeMirror = "java.lang.String"] | +- ArgumentList[] +- ArgumentList[] - +- MethodCall[@Failed = false, @Function = "java.util.stream.Collectors. toMap(java.util.function.Function, java.util.function.Function) -> java.util.stream.Collector>", @MethodName = "toMap", @TypeMirror = "java.util.stream.Collector>", @Unchecked = false, @VarargsCall = false] + +- MethodCall[@Failed = false, @Function = "java.util.stream.Collectors. toMap(java.util.function.Function, java.util.function.Function) -> java.util.stream.Collector>", @MethodName = "toMap", @TypeMirror = "java.util.stream.Collector>", @Unchecked = false, @VarargsCall = false] +- TypeExpression[@TypeMirror = "java.util.stream.Collectors"] | +- ClassType[@TypeMirror = "java.util.stream.Collectors"] +- ArgumentList[] +- MethodReference[@TypeMirror = "java.util.function.Function"] | +- TypeExpression[@TypeMirror = "java.lang.String"] | +- ClassType[@TypeMirror = "java.lang.String"] - +- LambdaExpression[@TypeMirror = "java.util.function.Function"] + +- LambdaExpression[@TypeMirror = "java.util.function.Function"] +- LambdaParameterList[] | +- LambdaParameter[@TypeMirror = "java.lang.String"] | +- ModifierList[] From ed5e862aa384301a9e3c99f037930342cb6d23c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:14:44 +0100 Subject: [PATCH 04/17] Bump rouge from 4.4.0 to 4.5.0 in the all-gems group across 1 directory (#5316) Bumps the all-gems group with 1 update in the / directory: [rouge](https://github.com/rouge-ruby/rouge). Updates `rouge` from 4.4.0 to 4.5.0 - [Release notes](https://github.com/rouge-ruby/rouge/releases) - [Changelog](https://github.com/rouge-ruby/rouge/blob/master/CHANGELOG.md) - [Commits](https://github.com/rouge-ruby/rouge/compare/v4.4.0...v4.5.0) --- updated-dependencies: - dependency-name: rouge dependency-type: direct:development update-type: version-update:semver-minor dependency-group: all-gems ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1f7805ea50..41dfc5878a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,7 +75,7 @@ GEM racc (1.8.1) rchardet (1.8.0) rexml (3.3.9) - rouge (4.4.0) + rouge (4.5.0) rufus-scheduler (3.9.2) fugit (~> 1.1, >= 1.11.1) safe_yaml (1.0.5) From e5a123698144993b6cf8808e6206fae3b4ff5d88 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 15:48:47 +0100 Subject: [PATCH 05/17] Update pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml --- .../lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml index 2679f0a8c5..2a743036a6 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml @@ -2135,7 +2135,7 @@ public class ObtainViaTest { ]]> - UnusedPrivateMethod with method reference + #5324 UnusedPrivateMethod with method reference 0 Date: Thu, 14 Nov 2024 15:50:35 +0100 Subject: [PATCH 06/17] [doc] Update release notes (#5324) --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 3e50f0fc86..5fa3ac04b6 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -19,6 +19,7 @@ This is a {{ site.pmd.release_type }} release. * [#1860](https://github.com/pmd/pmd/issues/1860): \[ant] Reflective access warnings on java > 9 and java < 17 * java * [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads + * [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas ### 🚨 API Changes From a79d3e6557381cdad139d1ab2ee5d7921f78a081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 14 Nov 2024 16:13:30 +0100 Subject: [PATCH 07/17] Add unit tests --- .../java/internal/JavaLanguageProperties.java | 2 +- .../internal/infer/InferenceContext.java | 1 + .../internal/infer/TypeInferenceLogger.java | 10 +- .../internal/infer/InferenceCtxUnitTests.java | 93 +++++++++++++++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java index 7fafea029e..7590d48f6f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java @@ -22,7 +22,7 @@ public class JavaLanguageProperties extends JvmLanguagePropertyBundle { PropertyFactory.enumProperty("xTypeInferenceLogging", EnumUtils.getEnumMap(InferenceLoggingVerbosity.class)) .desc("Verbosity of the type inference logging") - .defaultValue(InferenceLoggingVerbosity.DISABLED) + .defaultValue(InferenceLoggingVerbosity.VERBOSE) .build(); diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java index 73b843439f..8cc251fa0e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceContext.java @@ -525,6 +525,7 @@ final class InferenceContext { * we try again to make progress. */ private boolean solve(VarWalkStrategy walker) { + graphWasChanged = false; incorporate(); while (walker.hasNext()) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java index 2c9cfff9ef..cb7fe3e6d3 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/TypeInferenceLogger.java @@ -22,6 +22,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import net.sourceforge.pmd.lang.java.ast.JavaNode; +import net.sourceforge.pmd.lang.java.internal.JavaLanguageProperties; import net.sourceforge.pmd.lang.java.symbols.JTypeDeclSymbol; import net.sourceforge.pmd.lang.java.types.JMethodSig; import net.sourceforge.pmd.lang.java.types.JTypeMirror; @@ -34,6 +35,12 @@ import net.sourceforge.pmd.util.StringUtil; /** * A strategy to log the execution traces of {@link Infer}. + * The default does nothing, so the logger calls can be optimized out + * at runtime, while not having to check that logging is enabled at the + * call sites. + * + *

To enable logging for the CLI, use the language property ({@link JavaLanguageProperties}) + * {@code xTypeInferenceLogging}. From tests, see {@code JavaParsingHelper#logTypeInferenceVerbose()}. */ @SuppressWarnings("PMD.UncommentedEmptyMethodBody") public interface TypeInferenceLogger { @@ -64,8 +71,7 @@ public interface TypeInferenceLogger { default void applicabilityTest(InferenceContext ctx) { } - default void finishApplicabilityTest() { - } + default void finishApplicabilityTest() { } default void startArgsChecks() { } diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java index 5e33c6dd01..ba1d834261 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/internal/infer/InferenceCtxUnitTests.java @@ -8,7 +8,10 @@ import static net.sourceforge.pmd.lang.java.types.TestUtilitiesForTypesKt.captur import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.eqBound; import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.lower; import static net.sourceforge.pmd.lang.java.types.internal.infer.BaseTypeInferenceUnitTest.Bound.upper; +import static net.sourceforge.pmd.util.CollectionUtil.setOf; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -19,11 +22,17 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import java.util.List; +import java.util.Set; + +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; import net.sourceforge.pmd.lang.java.types.JTypeMirror; import net.sourceforge.pmd.lang.java.types.TypeOps; import net.sourceforge.pmd.lang.java.types.internal.infer.InferenceVar.BoundKind; +import net.sourceforge.pmd.lang.java.types.internal.infer.VarWalkStrategy.GraphWalk; +import net.sourceforge.pmd.util.IteratorUtil; /** * @@ -331,4 +340,88 @@ class InferenceCtxUnitTests extends BaseTypeInferenceUnitTest { assertThat(a, hasBoundsExactly(upper(ts.BOOLEAN.box()))); } + + private static @NotNull List> createBatchSetsFromGraph(InferenceContext ctx) { + GraphWalk graphWalk = new GraphWalk(ctx, false); + List> batches = IteratorUtil.toList(graphWalk); + return batches; + } + + @Test + void testGraphBuilding() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + List> batches = createBatchSetsFromGraph(ctx); + // no dependency: unordered + assertThat(batches, containsInAnyOrder(setOf(a), setOf(b))); + } + + @Test + void testGraphBuildingWithDependency() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // a -> b + addSubtypeConstraint(ctx, a, ts.arrayType(b)); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(b), setOf(a))); + } + + @Test + void testGraphBuildingWithDependency2() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // a -> b + // b -> a (because of propagation) + addSubtypeConstraint(ctx, a, b); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(b, a))); + } + + + + + @Test + void testGraphBuildingWithExtraDependency() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + + // b -> a + ctx.addInstantiationDependencies(setOf(b), setOf(a)); + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(a), setOf(b))); + } + + @Test + void testGraphBuildingWithDependencyCycle() { + InferenceContext ctx = emptyCtx(); + InferenceVar a = newIvar(ctx); + InferenceVar b = newIvar(ctx); + InferenceVar c = newIvar(ctx); + + // a -> b, b -> a, + // a -> c, b -> c + a.addBound(BoundKind.UPPER, b); + a.addBound(BoundKind.EQ, listType(c)); + b.addBound(BoundKind.LOWER, a); + b.addBound(BoundKind.LOWER, listType(c)); + + + List> batches = createBatchSetsFromGraph(ctx); + + assertThat(batches, contains(setOf(c), setOf(b, a))); + } + } From 2df68ed16888ce9945dfc960d5b51c2547d4c833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 14 Nov 2024 16:32:09 +0100 Subject: [PATCH 08/17] Disable type inf logging by default --- .../pmd/lang/java/internal/JavaLanguageProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java index 7590d48f6f..7fafea029e 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/internal/JavaLanguageProperties.java @@ -22,7 +22,7 @@ public class JavaLanguageProperties extends JvmLanguagePropertyBundle { PropertyFactory.enumProperty("xTypeInferenceLogging", EnumUtils.getEnumMap(InferenceLoggingVerbosity.class)) .desc("Verbosity of the type inference logging") - .defaultValue(InferenceLoggingVerbosity.VERBOSE) + .defaultValue(InferenceLoggingVerbosity.DISABLED) .build(); From 634a5252860d7e966109eef62ae3cb0973c6b491 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 17:07:37 +0100 Subject: [PATCH 09/17] [html] Test for a closing tag when determining node positions Fixes #5322 --- docs/pages/release_notes.md | 2 ++ .../pmd/lang/html/ast/LineNumbers.java | 11 ++++---- .../pmd/lang/html/cpd/HtmlCpdLexerTest.java | 9 +++++++ .../lang/html/cpd/testdata/InvalidHtml.html | 7 +++++ .../lang/html/cpd/testdata/InvalidHtml.txt | 22 +++++++++++++++ .../pmd/lang/html/cpd/testdata/MetaTag.html | 9 +++++++ .../pmd/lang/html/cpd/testdata/MetaTag.txt | 27 +++++++++++++++++++ 7 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.html create mode 100644 pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.txt create mode 100644 pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.html create mode 100644 pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.txt diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 5fa3ac04b6..3a1b90322b 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -20,6 +20,8 @@ This is a {{ site.pmd.release_type }} release. * java * [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads * [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas +* html + * [5322](https://github.com/pmd/pmd/issues/5322): \[html] CPD throws exception on when HTML file is missing closing tag ### 🚨 API Changes diff --git a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/LineNumbers.java b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/LineNumbers.java index 423b2772fb..5419b30e3a 100644 --- a/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/LineNumbers.java +++ b/pmd-html/src/main/java/net/sourceforge/pmd/lang/html/ast/LineNumbers.java @@ -50,15 +50,14 @@ class LineNumbers { nextIndex = determineLocation((AbstractHtmlNode) child, nextIndex); } - // autoclosing element, eg - boolean isAutoClose = n.getNumChildren() == 0 - && n instanceof ASTHtmlElement - // nextIndex is up to the closing > at this point - && htmlString.startsWith("/>", nextIndex - 2); + // explicitly closing element, eg. + boolean hasCloseElement = n instanceof ASTHtmlElement + // nextIndex is up to the closing tag at this point + && htmlString.startsWith("", nextIndex); if (n instanceof ASTHtmlDocument) { nextIndex = htmlString.length(); - } else if (n instanceof ASTHtmlElement && !isAutoClose) { + } else if (n instanceof ASTHtmlElement && hasCloseElement) { nextIndex += 2 + n.getXPathNodeName().length() + 1; // } else if (n instanceof ASTHtmlComment) { nextIndex += 4 + 3; // diff --git a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/cpd/HtmlCpdLexerTest.java b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/cpd/HtmlCpdLexerTest.java index 04db5c6152..088837d2ce 100644 --- a/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/cpd/HtmlCpdLexerTest.java +++ b/pmd-html/src/test/java/net/sourceforge/pmd/lang/html/cpd/HtmlCpdLexerTest.java @@ -21,4 +21,13 @@ class HtmlCpdLexerTest extends CpdTextComparisonTest { doTest("SimpleHtmlFile"); } + @Test + void invalidHtml() { + doTest("InvalidHtml"); + } + + @Test + void metaTag() { + doTest("MetaTag"); + } } diff --git a/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.html b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.html new file mode 100644 index 0000000000..73acc68e1d --- /dev/null +++ b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.html @@ -0,0 +1,7 @@ + + + + +

+ + diff --git a/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.txt b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.txt new file mode 100644 index 0000000000..2cc097ffd2 --- /dev/null +++ b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/InvalidHtml.txt @@ -0,0 +1,22 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [#document] 1 8 + [#doctype] 1 15 + [\n] 16 16 +L2 + [html] 1 7 + [\n] 17 17 +L3 + [body] 1 7 + [\n] 7 7 +L4 + [#comment] 1 36 + [\n] 37 37 +L5 + [div] 1 22 + [\n] 22 22 +L6 + [\n] 8 8 +L7 + [\n] 8 8 +EOF diff --git a/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.html b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.html new file mode 100644 index 0000000000..d8a96810a8 --- /dev/null +++ b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.txt b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.txt new file mode 100644 index 0000000000..0547e117b8 --- /dev/null +++ b/pmd-html/src/test/resources/net/sourceforge/pmd/lang/html/cpd/testdata/MetaTag.txt @@ -0,0 +1,27 @@ + [Image] or [Truncated image[ Bcol Ecol +L1 + [#document] 1 8 + [#doctype] 1 15 + [\n] 16 16 +L2 + [html] 1 7 + [\n] 17 17 +L3 + [head] 1 7 + [\n ] 7 4 +L4 + [#comment] 5 66 + [\n ] 67 4 +L5 + [meta] 5 27 + [\n] 27 27 +L6 + [\n] 8 8 +L7 + [body] 1 7 + [\n] 7 7 +L8 + [\n] 8 8 +L9 + [\n] 8 8 +EOF From bf388d7fd059aec33d38f6b2088470c04ea1aea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Thu, 14 Nov 2024 17:27:45 +0100 Subject: [PATCH 10/17] Propagate unknown type better when mref is unresolved --- .../types/internal/infer/ExprCheckHelper.java | 7 ++ .../java/types/internal/infer/ExprOps.java | 1 - .../lang/java/types/TypesTreeDumpTest.java | 5 ++ .../pmd/lang/java/types/AstTestUtil.kt | 1 + .../infer/UnresolvedTypesRecoveryTest.kt | 38 +++++++++ .../bestpractices/xml/UnusedPrivateMethod.xml | 41 ++++++++++ .../types/dumptests/UnresolvedThings.java | 16 ++++ .../java/types/dumptests/UnresolvedThings.txt | 80 +++++++++++++++++++ 8 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.java create mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.txt diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java index dc8955fcb0..f6521426e2 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprCheckHelper.java @@ -335,6 +335,13 @@ final class ExprCheckHelper { checker.checkExprConstraint(infCtx, capture(r2), r); } completeMethodRefInference(mref, nonWildcard, fun, exactMethod, true); + } else if (TypeOps.isUnresolved(mref.getTypeToSearch())) { + // Then this is neither an exact nor inexact method ref, + // we just don't know what it is. + + // The return values of the mref are assimilated to an (*unknown*) type. + checker.checkExprConstraint(infCtx, ts.UNKNOWN, fun.getReturnType()); + completeMethodRefInference(mref, nonWildcard, fun, ts.UNRESOLVED_METHOD, false); } else { // Otherwise, the method reference is inexact, and: diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprOps.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprOps.java index 8ea1cee3da..a04c91c55f 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprOps.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/types/internal/infer/ExprOps.java @@ -227,7 +227,6 @@ final class ExprOps { } } else { JClassType enclosing = mref.getEnclosingType(); - accessible = mref.getTypeToSearch() .streamMethods(TypeOps.accessibleMethodFilter(mref.getMethodName(), enclosing.getSymbol())) .collect(OverloadSet.collectMostSpecific(enclosing)); diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java index 9b8baaeca6..50d22c663d 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/lang/java/types/TypesTreeDumpTest.java @@ -55,6 +55,11 @@ class TypesTreeDumpTest extends BaseTreeDumpTest { doTest("NestedLambdasAndMethodCalls"); } + @Test + void testUnresolvedThings() { + doTest("UnresolvedThings"); + } + @Override protected @NonNull String normalize(@NonNull String str) { return super.normalize(str) diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt index 1545c93f7e..e5c04d1ac5 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/AstTestUtil.kt @@ -21,6 +21,7 @@ fun JavaNode.declaredMethodSignatures(): List = methodDeclarations() fun JavaNode.methodCalls(): DescendantNodeStream = descendants(ASTMethodCall::class.java) fun JavaNode.firstMethodCall() = methodCalls().crossFindBoundaries().firstOrThrow() +fun JavaNode.firstMethodCall(name: String) = methodCalls().crossFindBoundaries().filter { it.methodName == name }.firstOrThrow() fun JavaNode.ctorCalls(): DescendantNodeStream = descendants(ASTConstructorCall::class.java) fun JavaNode.firstCtorCall() = ctorCalls().crossFindBoundaries().firstOrThrow() diff --git a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/UnresolvedTypesRecoveryTest.kt b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/UnresolvedTypesRecoveryTest.kt index 24d7ec3c04..45c13cf569 100644 --- a/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/UnresolvedTypesRecoveryTest.kt +++ b/pmd-java/src/test/kotlin/net/sourceforge/pmd/lang/java/types/internal/infer/UnresolvedTypesRecoveryTest.kt @@ -664,4 +664,42 @@ class C { fooToInt.referencedMethod.symbol shouldBe toIntFun } } + + parserTest("Type inference should not resolve UNKNOWN bounded types to Object #5329") { + + val (acu, _) = parser.parseWithTypeInferenceSpy( + """ + import java.util.ArrayList; + import java.util.List; + import java.util.stream.Stream; + import java.util.stream.Collectors; + + class Foo { + public Item methodA(List loads) { + List items = new ArrayList<>(); + loads.stream() + // Here this collect call should have type + // Map<(*unknown*), List<*Item>> + // ie, key is unknown, not Object. + .collect(Collectors.groupingBy(Item::getValue)) + .forEach((a, b) -> items.add(buildItem(a, b))); + } + + private SummaryDto.ItemDto buildItem(BigDecimal a, List b) { + return SummaryDto.ItemDto.builder().build(); + } + } + """ + ) + + val collect = acu.firstMethodCall("collect") + val buildItem = acu.firstMethodCall("buildItem") + val (_, buildItemDecl) = acu.methodDeclarations().toList { it.symbol } + val (itemT) = acu.descendants(ASTClassType::class.java).toList { it.typeMirror } + + acu.withTypeDsl { + collect shouldHaveType java.util.Map::class[ts.UNKNOWN, java.util.List::class[itemT]] + buildItem.methodType.symbol shouldBe buildItemDecl + } + } }) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml index 2a743036a6..1a6dd1488d 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/bestpractices/xml/UnusedPrivateMethod.xml @@ -2177,4 +2177,45 @@ public class ObtainViaTest { record Library(Collection books) {} ]]> + + #5324 UnusedPrivateMethod with unresolved types + 0 + { + try { + return registerUser(email, firstName, lastName); + } catch (Exception e) { + throw new IllegalStateException("Failed to register user for " + email, e); + } + }); + // ... + return user; + } + + private User registerUser(String email, String firstName, String lastName) throws Exception { + // register user logic here... + } + } + ]]> + + + #5329 UnusedPrivateMethod with unresolved types + 0 + items = new ArrayList<>(); + loads.stream() + .collect(Collectors.groupingBy(Item::getValue)) + .forEach((a, b) -> items.add(buildItem(a, b))); + } + + private SummaryDto.ItemDto buildItem(BigDecimal a, List b) { + return SummaryDto.ItemDto.builder().build(); + } + } + ]]> + diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.java b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.java new file mode 100644 index 0000000000..83eb9d62b4 --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.java @@ -0,0 +1,16 @@ +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; +class Foo { + public User methodA(List loads) { + List items = new ArrayList<>(); + loads.stream() + .collect(Collectors.groupingBy(Item::getValue)) + .forEach((a, b) -> items.add(buildItem(a, b))); + } + + private SummaryDto.ItemDto buildItem(BigDecimal a, List b) { + return SummaryDto.ItemDto.builder().build(); + } +} \ No newline at end of file diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.txt b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.txt new file mode 100644 index 0000000000..32f1f2643e --- /dev/null +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/types/dumptests/UnresolvedThings.txt @@ -0,0 +1,80 @@ ++- CompilationUnit[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ImportDeclaration[] + +- ClassDeclaration[@TypeMirror = "Foo"] + +- ModifierList[] + +- ClassBody[] + +- MethodDeclaration[@Name = "methodA"] + | +- ModifierList[] + | +- ClassType[@TypeMirror = "*User"] + | +- FormalParameters[] + | | +- FormalParameter[@TypeMirror = "java.util.List<*Item>"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.util.List<*Item>"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "*Item"] + | | +- VariableId[@Name = "loads", @TypeMirror = "java.util.List<*Item>"] + | +- Block[] + | +- LocalVariableDeclaration[] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "java.util.List<*SummaryDto.ItemDto>"] + | | | +- TypeArguments[] + | | | +- ClassType[@TypeMirror = "*SummaryDto.ItemDto"] + | | +- VariableDeclarator[] + | | +- VariableId[@Name = "items", @TypeMirror = "java.util.List<*SummaryDto.ItemDto>"] + | | +- ConstructorCall[@Failed = false, @Function = "java.util.ArrayList<*SummaryDto.ItemDto>.new() -> java.util.ArrayList<*SummaryDto.ItemDto>", @MethodName = "new", @TypeMirror = "java.util.ArrayList<*SummaryDto.ItemDto>", @Unchecked = false, @VarargsCall = false] + | | +- ClassType[@TypeMirror = "java.util.ArrayList"] + | | | +- TypeArguments[] + | | +- ArgumentList[] + | +- ExpressionStatement[] + | +- MethodCall[@Failed = false, @Function = "java.util.Map<(*unknown*), java.util.List<*Item>>.forEach(java.util.function.BiConsumer>) -> void", @MethodName = "forEach", @TypeMirror = "void", @Unchecked = false, @VarargsCall = false] + | +- MethodCall[@Failed = false, @Function = "java.util.stream.Stream<*Item>. collect(java.util.stream.Collector>>) -> java.util.Map<(*unknown*), java.util.List<*Item>>", @MethodName = "collect", @TypeMirror = "java.util.Map<(*unknown*), java.util.List<*Item>>", @Unchecked = false, @VarargsCall = false] + | | +- MethodCall[@Failed = false, @Function = "java.util.Collection<*Item>.stream() -> java.util.stream.Stream<*Item>", @MethodName = "stream", @TypeMirror = "java.util.stream.Stream<*Item>", @Unchecked = false, @VarargsCall = false] + | | | +- VariableAccess[@Name = "loads", @TypeMirror = "java.util.List<*Item>"] + | | | +- ArgumentList[] + | | +- ArgumentList[] + | | +- MethodCall[@Failed = false, @Function = "java.util.stream.Collectors. groupingBy(java.util.function.Function) -> java.util.stream.Collector<*Item, java.lang.Object, java.util.Map<(*unknown*), java.util.List<*Item>>>", @MethodName = "groupingBy", @TypeMirror = "java.util.stream.Collector<*Item, java.lang.Object, java.util.Map<(*unknown*), java.util.List<*Item>>>", @Unchecked = false, @VarargsCall = false] + | | +- TypeExpression[@TypeMirror = "java.util.stream.Collectors"] + | | | +- ClassType[@TypeMirror = "java.util.stream.Collectors"] + | | +- ArgumentList[] + | | +- MethodReference[@TypeMirror = "java.util.function.Function<*Item, (*unknown*)>"] + | | +- AmbiguousName[@TypeMirror = "(*unknown*)"] + | +- ArgumentList[] + | +- LambdaExpression[@TypeMirror = "java.util.function.BiConsumer<(*unknown*), java.util.List<*Item>>"] + | +- LambdaParameterList[] + | | +- LambdaParameter[@TypeMirror = "(*unknown*)"] + | | | +- ModifierList[] + | | | +- VariableId[@Name = "a", @TypeMirror = "(*unknown*)"] + | | +- LambdaParameter[@TypeMirror = "java.util.List<*Item>"] + | | +- ModifierList[] + | | +- VariableId[@Name = "b", @TypeMirror = "java.util.List<*Item>"] + | +- MethodCall[@Failed = false, @Function = "java.util.List<*SummaryDto.ItemDto>.add(*SummaryDto.ItemDto) -> boolean", @MethodName = "add", @TypeMirror = "boolean", @Unchecked = false, @VarargsCall = false] + | +- VariableAccess[@Name = "items", @TypeMirror = "java.util.List<*SummaryDto.ItemDto>"] + | +- ArgumentList[] + | +- MethodCall[@Failed = false, @Function = "Foo.buildItem(*BigDecimal, java.util.List<*Item>) -> *SummaryDto.ItemDto", @MethodName = "buildItem", @TypeMirror = "*SummaryDto.ItemDto", @Unchecked = false, @VarargsCall = false] + | +- ArgumentList[] + | +- VariableAccess[@Name = "a", @TypeMirror = "(*unknown*)"] + | +- VariableAccess[@Name = "b", @TypeMirror = "java.util.List<*Item>"] + +- MethodDeclaration[@Name = "buildItem"] + +- ModifierList[] + +- ClassType[@TypeMirror = "*SummaryDto.ItemDto"] + +- FormalParameters[] + | +- FormalParameter[@TypeMirror = "*BigDecimal"] + | | +- ModifierList[] + | | +- ClassType[@TypeMirror = "*BigDecimal"] + | | +- VariableId[@Name = "a", @TypeMirror = "*BigDecimal"] + | +- FormalParameter[@TypeMirror = "java.util.List<*Item>"] + | +- ModifierList[] + | +- ClassType[@TypeMirror = "java.util.List<*Item>"] + | | +- TypeArguments[] + | | +- ClassType[@TypeMirror = "*Item"] + | +- VariableId[@Name = "b", @TypeMirror = "java.util.List<*Item>"] + +- Block[] + +- ReturnStatement[] + +- MethodCall[@Failed = true, @Function = "(*unknown*).(*unknown method*)() -> (*unknown*)", @MethodName = "build", @TypeMirror = "(*unknown*)", @Unchecked = false, @VarargsCall = false] + +- MethodCall[@Failed = true, @Function = "(*unknown*).(*unknown method*)() -> (*unknown*)", @MethodName = "builder", @TypeMirror = "(*unknown*)", @Unchecked = false, @VarargsCall = false] + | +- AmbiguousName[@TypeMirror = "(*unknown*)"] + | +- ArgumentList[] + +- ArgumentList[] From 3fdbf7d6cbaaa78f2edc2f48922beeb5c2e4a9ce Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 17:48:08 +0100 Subject: [PATCH 11/17] [java] InsufficientStringBufferDeclaration: Fix CCE for Character Fixes #5314 --- docs/pages/release_notes.md | 2 ++ ...sufficientStringBufferDeclarationRule.java | 8 +++++++- .../InsufficientStringBufferDeclaration.xml | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 5fa3ac04b6..3893f1a820 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -20,6 +20,8 @@ This is a {{ site.pmd.release_type }} release. * java * [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads * [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas +* java-performance + * [#5314](https://github.com/pmd/pmd/issues/5314): \[java] InsufficientStringBufferDeclarationRule: Lack of handling for char type parameters ### 🚨 API Changes diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java index a6fabf91a2..5acd063c15 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/performance/InsufficientStringBufferDeclarationRule.java @@ -240,6 +240,12 @@ public class InsufficientStringBufferDeclarationRule extends AbstractJavaRulecha private int calculateExpression(ASTExpression expression) { Object value = expression.getConstValue(); - return value == null ? State.UNKNOWN_CAPACITY : (Integer) value; + if (value == null) { + return State.UNKNOWN_CAPACITY; + } + if (value instanceof Character) { + return (Character) value; + } + return (Integer) value; } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InsufficientStringBufferDeclaration.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InsufficientStringBufferDeclaration.xml index ec267fcfcc..bd5d364eb1 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InsufficientStringBufferDeclaration.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/performance/xml/InsufficientStringBufferDeclaration.xml @@ -1419,4 +1419,23 @@ public class LiteralExpression { } ]]> + + + #5314 [java] InsufficientStringBufferDeclarationRule: Lack of handling for char type parameters + 0 + + From 01b8ca765bc16a57bac3bb8a14f2c13839ae2dd7 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 17:48:26 +0100 Subject: [PATCH 12/17] Add @chenguangqi as a contributor --- .all-contributorsrc | 9 ++ docs/pages/pmd/projectdocs/credits.md | 172 +++++++++++++------------- 2 files changed, 96 insertions(+), 85 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 95ebc05d6e..1d4a930f38 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -7865,6 +7865,15 @@ "contributions": [ "code" ] + }, + { + "login": "chenguangqi", + "name": "天热吃西瓜", + "avatar_url": "https://avatars.githubusercontent.com/u/6231010?v=4", + "profile": "http://chenguangqi.github.io/", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 9497ea7378..7b6a55aec6 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -350,770 +350,772 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d JJengility
JJengility

🐛 Jake Hemmerle
Jake Hemmerle

🐛 + Jakub Dupak
Jakub Dupak

💻 James Harrison
James Harrison

🐛 💻 Jamie Bisotti
Jamie Bisotti

🐛 Jan
Jan

🐛 Jan Aertgeerts
Jan Aertgeerts

💻 🐛 - Jan Brümmer
Jan Brümmer

🐛 + Jan Brümmer
Jan Brümmer

🐛 Jan Tříska
Jan Tříska

🐛 Jan-Lukas Else
Jan-Lukas Else

🐛 Jason Qiu
Jason Qiu

💻 📖 Jason Williams
Jason Williams

🐛 Javier Spagnoletti
Javier Spagnoletti

🐛 Jean-Paul Mayer
Jean-Paul Mayer

🐛 - Jean-Simon Larochelle
Jean-Simon Larochelle

🐛 + Jean-Simon Larochelle
Jean-Simon Larochelle

🐛 Jeff Bartolotta
Jeff Bartolotta

💻 🐛 Jeff Hube
Jeff Hube

💻 🐛 Jeff Jensen
Jeff Jensen

🐛 Jeff May
Jeff May

🐛 Jens Gerdes
Jens Gerdes

🐛 Jeroen Borgers
Jeroen Borgers

🐛 💻 📢 - Jeroen Meijer
Jeroen Meijer

🐛 + Jeroen Meijer
Jeroen Meijer

🐛 Jeroen van Wilgenburg
Jeroen van Wilgenburg

📖 Jerome Russ
Jerome Russ

🐛 JerritEic
JerritEic

💻 📖 🐛 Jiri Pejchal
Jiri Pejchal

🐛 Jithin Sunny
Jithin Sunny

🐛 Jiří Škorpil
Jiří Škorpil

🐛 - Joao Machado
Joao Machado

🐛 + Joao Machado
Joao Machado

🐛 Jochen Krauss
Jochen Krauss

🐛 Johan Hammar
Johan Hammar

🐛 John Karp
John Karp

🐛 John Zhang
John Zhang

🐛 John-Teng
John-Teng

💻 🐛 Jon Moroney
Jon Moroney

💻 🐛 - Jonas Geiregat
Jonas Geiregat

🐛 + Jonas Geiregat
Jonas Geiregat

🐛 Jonas Keßler
Jonas Keßler

🐛 Jonathan Wiesel
Jonathan Wiesel

💻 🐛 Jordan
Jordan

🐛 Jordi Llach
Jordi Llach

🐛 Jorge Solórzano
Jorge Solórzano

🐛 JorneVL
JorneVL

🐛 - Jose Palafox
Jose Palafox

🐛 + Jose Palafox
Jose Palafox

🐛 Jose Stovall
Jose Stovall

🐛 Joseph
Joseph

💻 Joseph Heenan
Joseph Heenan

🐛 Josh Feingold
Josh Feingold

💻 🐛 Josh Holthaus
Josh Holthaus

🐛 Joshua S Arquilevich
Joshua S Arquilevich

🐛 - João Dinis Ferreira
João Dinis Ferreira

📖 + João Dinis Ferreira
João Dinis Ferreira

📖 João Ferreira
João Ferreira

💻 🐛 João Pedro Schmitt
João Pedro Schmitt

🐛 Juan Martín Sotuyo Dodero
Juan Martín Sotuyo Dodero

💻 📖 🐛 🚧 Juan Pablo Civile
Juan Pablo Civile

🐛 Julian Voronetsky
Julian Voronetsky

🐛 Julien
Julien

🐛 - Julius
Julius

🐛 + Julius
Julius

🐛 JustPRV
JustPRV

🐛 Justin Stroud
Justin Stroud

💻 Jörn Huxhorn
Jörn Huxhorn

🐛 KThompso
KThompso

🐛 Kai Amundsen
Kai Amundsen

🐛 Karel Vervaeke
Karel Vervaeke

🐛 - Karl-Andero Mere
Karl-Andero Mere

🐛 + Karl-Andero Mere
Karl-Andero Mere

🐛 Karl-Philipp Richter
Karl-Philipp Richter

🐛 Karsten Silz
Karsten Silz

🐛 Kazuma Watanabe
Kazuma Watanabe

🐛 Kev
Kev

🐛 Keve Müller
Keve Müller

🐛 Kevin Guerra
Kevin Guerra

💻 - Kevin Jones
Kevin Jones

🐛 💻 + Kevin Jones
Kevin Jones

🐛 💻 Kevin Poorman
Kevin Poorman

🐛 Kevin Wayne
Kevin Wayne

🐛 Kieran Black
Kieran Black

🐛 Kirill Zubov
Kirill Zubov

🐛 Kirk Clemens
Kirk Clemens

💻 🐛 Klaus Hartl
Klaus Hartl

🐛 - Koen Van Looveren
Koen Van Looveren

🐛 + Koen Van Looveren
Koen Van Looveren

🐛 Kris Scheibe
Kris Scheibe

💻 🐛 Krystian Dabrowski
Krystian Dabrowski

🐛 💻 Kunal Thanki
Kunal Thanki

🐛 LaLucid
LaLucid

💻 Larry Diamond
Larry Diamond

💻 🐛 Lars Knickrehm
Lars Knickrehm

🐛 - Laurent Bovet
Laurent Bovet

🐛 💻 + Laurent Bovet
Laurent Bovet

🐛 💻 Leo Gutierrez
Leo Gutierrez

🐛 LiGaOg
LiGaOg

💻 Liam Sharp
Liam Sharp

🐛 Lintsi
Lintsi

🐛 Linus Fernandes
Linus Fernandes

🐛 Lixon Lookose
Lixon Lookose

🐛 - Logesh
Logesh

🐛 + Logesh
Logesh

🐛 Lorenzo Gabriele
Lorenzo Gabriele

🐛 Loïc Ledoyen
Loïc Ledoyen

🐛 Lucas
Lucas

🐛 Lucas Silva
Lucas Silva

🐛 Lucas Soncini
Lucas Soncini

💻 🐛 Luis Alcantar
Luis Alcantar

💻 - Lukas Gräf
Lukas Gräf

💻 + Lukas Gräf
Lukas Gräf

💻 Lukasz Slonina
Lukasz Slonina

🐛 Lukebray
Lukebray

🐛 Lynn
Lynn

💻 🐛 Lyor Goldstein
Lyor Goldstein

🐛 MCMicS
MCMicS

🐛 Macarse
Macarse

🐛 - Machine account for PMD
Machine account for PMD

💻 + Machine account for PMD
Machine account for PMD

💻 Maciek Siemczyk
Maciek Siemczyk

🐛 Maikel Steneker
Maikel Steneker

💻 🐛 Maksim Moiseikin
Maksim Moiseikin

🐛 Manfred Koch
Manfred Koch

🐛 Manuel Moya Ferrer
Manuel Moya Ferrer

💻 🐛 Manuel Ryan
Manuel Ryan

🐛 - Marat Vyshegorodtsev
Marat Vyshegorodtsev

🐛 + Marat Vyshegorodtsev
Marat Vyshegorodtsev

🐛 Marcel Härle
Marcel Härle

🐛 Marcello Fialho
Marcello Fialho

🐛 Marcin Dąbrowski
Marcin Dąbrowski

💻 Marcin Rataj
Marcin Rataj

🐛 Marcono1234
Marcono1234

🐛 Mark Adamcin
Mark Adamcin

🐛 - Mark Hall
Mark Hall

💻 🐛 + Mark Hall
Mark Hall

💻 🐛 Mark Kolich
Mark Kolich

🐛 Mark Pritchard
Mark Pritchard

🐛 Markus Rathgeb
Markus Rathgeb

🐛 Marquis Wang
Marquis Wang

🐛 MartGit
MartGit

🐛 Martin Feldsztejn
Martin Feldsztejn

🐛 - Martin Lehmann
Martin Lehmann

🐛 + Martin Lehmann
Martin Lehmann

🐛 Martin Spamer
Martin Spamer

🐛 Martin Tarjányi
Martin Tarjányi

🐛 MatFl
MatFl

🐛 Mateusz Stefanski
Mateusz Stefanski

🐛 Mathieu Gouin
Mathieu Gouin

🐛 MatiasComercio
MatiasComercio

💻 🐛 - Matt Benson
Matt Benson

🐛 + Matt Benson
Matt Benson

🐛 Matt De Poorter
Matt De Poorter

🐛 Matt Hargett
Matt Hargett

💻 💵 Matt Harrah
Matt Harrah

🐛 Matt Nelson
Matt Nelson

🐛 Matthew Amos
Matthew Amos

🐛 Matthew Duggan
Matthew Duggan

🐛 - Matthew Hall
Matthew Hall

🐛 + Matthew Hall
Matthew Hall

🐛 Matthew Rossner
Matthew Rossner

🐛 Matías Fraga
Matías Fraga

💻 🐛 Maxime Robert
Maxime Robert

💻 🐛 MetaBF
MetaBF

🐛 Metin Dagcilar
Metin Dagcilar

🐛 Michael
Michael

🐛 - Michael Bell
Michael Bell

🐛 + Michael Bell
Michael Bell

🐛 Michael Bernstein
Michael Bernstein

🐛 Michael Clay
Michael Clay

🐛 Michael Dombrowski
Michael Dombrowski

🐛 Michael Hausegger
Michael Hausegger

🐛 Michael Hoefer
Michael Hoefer

🐛 Michael Kolesnikov
Michael Kolesnikov

🐛 - Michael Möbius
Michael Möbius

🐛 + Michael Möbius
Michael Möbius

🐛 Michael N. Lipp
Michael N. Lipp

🐛 Michael Pellegrini
Michael Pellegrini

🐛 Michal Kordas
Michal Kordas

🐛 Michał Borek
Michał Borek

🐛 Michał Kuliński
Michał Kuliński

🐛 Miguel Núñez Díaz-Montes
Miguel Núñez Díaz-Montes

🐛 - Mihai Ionut
Mihai Ionut

🐛 + Mihai Ionut
Mihai Ionut

🐛 Mikhail Kuchma
Mikhail Kuchma

🐛 Mirek Hankus
Mirek Hankus

🐛 Mitch Spano
Mitch Spano

🐛 Mladjan Gadzic
Mladjan Gadzic

🐛 MrAngry52
MrAngry52

🐛 Muminur Choudhury
Muminur Choudhury

🐛 - Mykhailo Palahuta
Mykhailo Palahuta

💻 🐛 + Mykhailo Palahuta
Mykhailo Palahuta

💻 🐛 Nagendra Kumar Singh
Nagendra Kumar Singh

🐛 Nahuel Barrios
Nahuel Barrios

🐛 Nakul Sharma
Nakul Sharma

🐛 Nathan Braun
Nathan Braun

🐛 Nathan Reynolds
Nathan Reynolds

🐛 Nathan Reynolds
Nathan Reynolds

🐛 - Nathanaël
Nathanaël

🐛 + Nathanaël
Nathanaël

🐛 Naveen
Naveen

💻 Nazdravi
Nazdravi

🐛 Neha-Dhonde
Neha-Dhonde

🐛 Nicholas Doyle
Nicholas Doyle

🐛 Nick Butcher
Nick Butcher

🐛 Nico Gallinal
Nico Gallinal

🐛 - Nicola Dal Maso
Nicola Dal Maso

🐛 + Nicola Dal Maso
Nicola Dal Maso

🐛 Nicolas Filotto
Nicolas Filotto

💻 Nicolas Vervelle
Nicolas Vervelle

🐛 Nicolas Vuillamy
Nicolas Vuillamy

📖 Nikita Chursin
Nikita Chursin

🐛 Niklas Baudy
Niklas Baudy

🐛 Nikolas Havrikov
Nikolas Havrikov

🐛 - Nilesh Virkar
Nilesh Virkar

🐛 + Nilesh Virkar
Nilesh Virkar

🐛 Nimit Patel
Nimit Patel

🐛 Niranjan Harpale
Niranjan Harpale

🐛 Nirvik Patel
Nirvik Patel

💻 Noah Sussman
Noah Sussman

🐛 Noah0120
Noah0120

🐛 Noam Tamim
Noam Tamim

🐛 - Noel Grandin
Noel Grandin

🐛 + Noel Grandin
Noel Grandin

🐛 Olaf Haalstra
Olaf Haalstra

🐛 Oleg Andreych
Oleg Andreych

💻 🐛 Oleg Pavlenko
Oleg Pavlenko

🐛 Oleksii Dykov
Oleksii Dykov

💻 🐛 Oliver Eikemeier
Oliver Eikemeier

🐛 Oliver Siegmar
Oliver Siegmar

💵 - Olivier Parent
Olivier Parent

💻 🐛 + Olivier Parent
Olivier Parent

💻 🐛 Ollie Abbey
Ollie Abbey

💻 🐛 Ondrej Kratochvil
Ondrej Kratochvil

🐛 OverDrone
OverDrone

🐛 Ozan Gulle
Ozan Gulle

💻 🐛 PUNEET JAIN
PUNEET JAIN

🐛 Parbati Bose
Parbati Bose

🐛 - Paul Berg
Paul Berg

🐛 + Paul Berg
Paul Berg

🐛 Paul Guyot
Paul Guyot

💻 Pavel Bludov
Pavel Bludov

🐛 Pavel Mička
Pavel Mička

🐛 Pedro Nuno Santos
Pedro Nuno Santos

🐛 Pedro Rijo
Pedro Rijo

🐛 Pelisse Romain
Pelisse Romain

💻 📖 🐛 - Per Abich
Per Abich

💻 + Per Abich
Per Abich

💻 Pete Davids
Pete Davids

🐛 Peter Bruin
Peter Bruin

🐛 Peter Chittum
Peter Chittum

💻 🐛 Peter Cudmore
Peter Cudmore

🐛 Peter Kasson
Peter Kasson

🐛 Peter Kofler
Peter Kofler

🐛 - Peter Paul Bakker
Peter Paul Bakker

💻 + Peter Paul Bakker
Peter Paul Bakker

💻 Peter Rader
Peter Rader

🐛 Pham Hai Trung
Pham Hai Trung

🐛 Philip Graf
Philip Graf

💻 🐛 Philip Hachey
Philip Hachey

🐛 Philippe Ozil
Philippe Ozil

🐛 Phinehas Artemix
Phinehas Artemix

🐛 - Phokham Nonava
Phokham Nonava

🐛 + Phokham Nonava
Phokham Nonava

🐛 Pim van der Loos
Pim van der Loos

💻 ⚠️ Piotr Szymański
Piotr Szymański

🐛 Piotrek Żygieło
Piotrek Żygieło

💻 🐛 📖 Pranay Jaiswal
Pranay Jaiswal

🐛 Prasad Kamath
Prasad Kamath

🐛 Prasanna
Prasanna

🐛 - Presh-AR
Presh-AR

🐛 + Presh-AR
Presh-AR

🐛 Puneet1726
Puneet1726

🐛 RBRi
RBRi

🐛 Rafael Cortês
Rafael Cortês

🐛 RaheemShaik999
RaheemShaik999

🐛 RajeshR
RajeshR

💻 🐛 Ramachandra Mohan
Ramachandra Mohan

🐛 - Ramel0921
Ramel0921

🐛 + Ramel0921
Ramel0921

🐛 Raquel Pau
Raquel Pau

🐛 Ravikiran Janardhana
Ravikiran Janardhana

🐛 Reda Benhemmouche
Reda Benhemmouche

🐛 Reinhard Schiedermeier
Reinhard Schiedermeier

🐛 Renato Oliveira
Renato Oliveira

💻 🐛 Rich DiCroce
Rich DiCroce

🐛 - Richard Corfield
Richard Corfield

💻 + Richard Corfield
Richard Corfield

💻 Richard Corfield
Richard Corfield

🐛 💻 Riot R1cket
Riot R1cket

🐛 Rishabh Jain
Rishabh Jain

🐛 RishabhDeep Singh
RishabhDeep Singh

🐛 Rob Baillie
Rob Baillie

🐛 Robbie Martinus
Robbie Martinus

💻 🐛 - Robert Henry
Robert Henry

🐛 + Robert Henry
Robert Henry

🐛 Robert Mihaly
Robert Mihaly

🐛 Robert Painsi
Robert Painsi

🐛 Robert Russell
Robert Russell

🐛 Robert Sösemann
Robert Sösemann

💻 📖 📢 🐛 Robert Whitebit
Robert Whitebit

🐛 Robin Richtsfeld
Robin Richtsfeld

🐛 - Robin Stocker
Robin Stocker

💻 🐛 + Robin Stocker
Robin Stocker

💻 🐛 Robin Wils
Robin Wils

🐛 RochusOest
RochusOest

🐛 Rodolfo Noviski
Rodolfo Noviski

🐛 Rodrigo Casara
Rodrigo Casara

🐛 Rodrigo Fernandes
Rodrigo Fernandes

🐛 Roman Salvador
Roman Salvador

💻 🐛 - Ronald Blaschke
Ronald Blaschke

🐛 + Ronald Blaschke
Ronald Blaschke

🐛 Róbert Papp
Róbert Papp

🐛 Saikat Sengupta
Saikat Sengupta

🐛 Saksham Handu
Saksham Handu

🐛 Saladoc
Saladoc

🐛 Salesforce Bob Lightning
Salesforce Bob Lightning

🐛 Sam Carlberg
Sam Carlberg

🐛 - Sascha Riemer
Sascha Riemer

🐛 + Sascha Riemer
Sascha Riemer

🐛 Sashko
Sashko

💻 Satoshi Kubo
Satoshi Kubo

🐛 Scott Kennedy
Scott Kennedy

🐛 Scott Wells
Scott Wells

🐛 💻 Scrates1
Scrates1

🐛 💻 Scrsloota
Scrsloota

💻 - Sebastian Bögl
Sebastian Bögl

🐛 + Sebastian Bögl
Sebastian Bögl

🐛 Sebastian Davids
Sebastian Davids

🐛 Sebastian Schuberth
Sebastian Schuberth

🐛 Sebastian Schwarz
Sebastian Schwarz

🐛 Seren
Seren

🐛 💻 Sergey Gorbaty
Sergey Gorbaty

🐛 Sergey Kozlov
Sergey Kozlov

🐛 - Sergey Yanzin
Sergey Yanzin

💻 🐛 + Sergey Yanzin
Sergey Yanzin

💻 🐛 Seth Wilcox
Seth Wilcox

💻 Shai Bennathan
Shai Bennathan

🐛 💻 Shubham
Shubham

💻 🐛 Simon Abykov
Simon Abykov

💻 🐛 Simon Xiao
Simon Xiao

🐛 Srinivasan Venkatachalam
Srinivasan Venkatachalam

🐛 - Stanislav Gromov
Stanislav Gromov

🐛 + Stanislav Gromov
Stanislav Gromov

🐛 Stanislav Myachenkov
Stanislav Myachenkov

💻 Stefan Birkner
Stefan Birkner

🐛 Stefan Bohn
Stefan Bohn

🐛 Stefan Endrullis
Stefan Endrullis

🐛 Stefan Klöss-Schuster
Stefan Klöss-Schuster

🐛 Stefan Wolf
Stefan Wolf

🐛 - Stephan H. Wissel
Stephan H. Wissel

🐛 + Stephan H. Wissel
Stephan H. Wissel

🐛 Stephen
Stephen

🐛 Stephen Carter
Stephen Carter

🐛 Stephen Friedrich
Stephen Friedrich

🐛 Steve Babula
Steve Babula

💻 Steven Stearns
Steven Stearns

🐛 💻 Stexxe
Stexxe

🐛 - Stian Lågstad
Stian Lågstad

🐛 + Stian Lågstad
Stian Lågstad

🐛 StuartClayton5
StuartClayton5

🐛 Supun Arunoda
Supun Arunoda

🐛 Suren Abrahamyan
Suren Abrahamyan

🐛 Suvashri
Suvashri

📖 SwatiBGupta1110
SwatiBGupta1110

🐛 SyedThoufich
SyedThoufich

🐛 - Szymon Sasin
Szymon Sasin

🐛 + Szymon Sasin
Szymon Sasin

🐛 T-chuangxin
T-chuangxin

🐛 TERAI Atsuhiro
TERAI Atsuhiro

🐛 TIOBE Software
TIOBE Software

💻 🐛 Tarush Singh
Tarush Singh

💻 Taylor Smock
Taylor Smock

🐛 Techeira Damián
Techeira Damián

💻 🐛 - Ted Husted
Ted Husted

🐛 + Ted Husted
Ted Husted

🐛 TehBakker
TehBakker

🐛 The Gitter Badger
The Gitter Badger

🐛 Theodoor
Theodoor

🐛 Thiago Henrique Hüpner
Thiago Henrique Hüpner

🐛 Thibault Meyer
Thibault Meyer

🐛 Thomas Güttler
Thomas Güttler

🐛 - Thomas Jones-Low
Thomas Jones-Low

🐛 + Thomas Jones-Low
Thomas Jones-Low

🐛 Thomas Smith
Thomas Smith

💻 🐛 ThrawnCA
ThrawnCA

🐛 Thu Vo
Thu Vo

🐛 Thunderforge
Thunderforge

💻 🐛 Tim van der Lippe
Tim van der Lippe

🐛 Tobias Weimer
Tobias Weimer

💻 🐛 - Tom Copeland
Tom Copeland

🐛 💻 📖 + Tom Copeland
Tom Copeland

🐛 💻 📖 Tom Daly
Tom Daly

🐛 Tomas
Tomas

🐛 Tomer Figenblat
Tomer Figenblat

🐛 Tomi De Lucca
Tomi De Lucca

💻 🐛 Tony
Tony

📖 Torsten Kleiber
Torsten Kleiber

🐛 - TrackerSB
TrackerSB

🐛 + TrackerSB
TrackerSB

🐛 Tyson Stewart
Tyson Stewart

🐛 Ullrich Hafner
Ullrich Hafner

🐛 Utku Cuhadaroglu
Utku Cuhadaroglu

💻 🐛 Valentin Brandl
Valentin Brandl

🐛 Valeria
Valeria

🐛 Valery Yatsynovich
Valery Yatsynovich

📖 - Vasily Anisimov
Vasily Anisimov

🐛 + Vasily Anisimov
Vasily Anisimov

🐛 Vedant Chokshi
Vedant Chokshi

🐛 Vibhor Goyal
Vibhor Goyal

🐛 Vickenty Fesunov
Vickenty Fesunov

🐛 Victor Noël
Victor Noël

🐛 Vincent Galloy
Vincent Galloy

💻 Vincent HUYNH
Vincent HUYNH

🐛 - Vincent Maurin
Vincent Maurin

🐛 + Vincent Maurin
Vincent Maurin

🐛 Vincent Privat
Vincent Privat

🐛 Vishhwas
Vishhwas

🐛 Vishv_Android
Vishv_Android

🐛 Vitaly
Vitaly

🐛 Vitaly Polonetsky
Vitaly Polonetsky

🐛 Vojtech Polivka
Vojtech Polivka

🐛 - Vsevolod Zholobov
Vsevolod Zholobov

🐛 + Vsevolod Zholobov
Vsevolod Zholobov

🐛 Vyom Yadav
Vyom Yadav

💻 Wang Shidong
Wang Shidong

🐛 Waqas Ahmed
Waqas Ahmed

🐛 Wayne J. Earl
Wayne J. Earl

🐛 Wchenghui
Wchenghui

🐛 Wener
Wener

💻 - Will Winder
Will Winder

🐛 + Will Winder
Will Winder

🐛 William Brockhus
William Brockhus

💻 🐛 Wilson Kurniawan
Wilson Kurniawan

🐛 Wim Deblauwe
Wim Deblauwe

🐛 Woongsik Choi
Woongsik Choi

🐛 XenoAmess
XenoAmess

💻 🐛 Yang
Yang

💻 - YaroslavTER
YaroslavTER

🐛 + YaroslavTER
YaroslavTER

🐛 Yasar Shaikh
Yasar Shaikh

💻 Young Chan
Young Chan

💻 🐛 YuJin Kim
YuJin Kim

🐛 Yuri Dolzhenko
Yuri Dolzhenko

🐛 Yurii Dubinka
Yurii Dubinka

🐛 Zoltan Farkas
Zoltan Farkas

🐛 - Zustin
Zustin

🐛 + Zustin
Zustin

🐛 aaronhurst-google
aaronhurst-google

🐛 💻 alexmodis
alexmodis

🐛 andreoss
andreoss

🐛 andrey81inmd
andrey81inmd

💻 🐛 anicoara
anicoara

🐛 arunprasathav
arunprasathav

🐛 - asiercamara
asiercamara

🐛 + asiercamara
asiercamara

🐛 astillich-igniti
astillich-igniti

💻 avesolovksyy
avesolovksyy

🐛 avishvat
avishvat

🐛 avivmu
avivmu

🐛 axelbarfod1
axelbarfod1

🐛 b-3-n
b-3-n

🐛 - balbhadra9
balbhadra9

🐛 + balbhadra9
balbhadra9

🐛 base23de
base23de

🐛 bergander
bergander

🐛 💻 berkam
berkam

💻 🐛 breizh31
breizh31

🐛 caesarkim
caesarkim

🐛 carolyujing
carolyujing

🐛 - cbfiddle
cbfiddle

🐛 + cbfiddle
cbfiddle

🐛 cesares-basilico
cesares-basilico

🐛 chrite
chrite

🐛 ciufudean
ciufudean

📖 cobratbq
cobratbq

🐛 coladict
coladict

🐛 cosmoJFH
cosmoJFH

🐛 - cristalp
cristalp

🐛 + cristalp
cristalp

🐛 crunsk
crunsk

🐛 cwholmes
cwholmes

🐛 cyberjj999
cyberjj999

🐛 cyw3
cyw3

🐛 📖 d1ss0nanz
d1ss0nanz

🐛 dague1
dague1

📖 - dalizi007
dalizi007

💻 + dalizi007
dalizi007

💻 danbrycefairsailcom
danbrycefairsailcom

🐛 dariansanity
dariansanity

🐛 darrenmiliband
darrenmiliband

🐛 davidburstrom
davidburstrom

🐛 dbirkman-paloalto
dbirkman-paloalto

🐛 deepak-patra
deepak-patra

🐛 - dependabot[bot]
dependabot[bot]

💻 🐛 + dependabot[bot]
dependabot[bot]

💻 🐛 dinesh150
dinesh150

🐛 diziaq
diziaq

🐛 dreaminpast123
dreaminpast123

🐛 duanyanan
duanyanan

🐛 dutt-sanjay
dutt-sanjay

🐛 duursma
duursma

💻 - dylanleung
dylanleung

🐛 + dylanleung
dylanleung

🐛 dzeigler
dzeigler

🐛 eant60
eant60

🐛 ekkirala
ekkirala

🐛 emersonmoura
emersonmoura

🐛 emouty
emouty

💻 🐛 eugenepugach
eugenepugach

🐛 - fairy
fairy

🐛 + fairy
fairy

🐛 filiprafalowicz
filiprafalowicz

💻 flxbl-io
flxbl-io

💵 foxmason
foxmason

🐛 frankegabor
frankegabor

🐛 frankl
frankl

🐛 freafrea
freafrea

🐛 - fsapatin
fsapatin

🐛 + fsapatin
fsapatin

🐛 gearsethenry
gearsethenry

🐛 gracia19
gracia19

🐛 gudzpoz
gudzpoz

🐛 guo fei
guo fei

🐛 gurmsc5
gurmsc5

🐛 gwilymatgearset
gwilymatgearset

💻 🐛 - haigsn
haigsn

🐛 + haigsn
haigsn

🐛 hemanshu070
hemanshu070

🐛 henrik242
henrik242

🐛 hongpuwu
hongpuwu

🐛 hvbtup
hvbtup

💻 🐛 igniti GmbH
igniti GmbH

🐛 ilovezfs
ilovezfs

🐛 - imax-erik
imax-erik

🐛 + imax-erik
imax-erik

🐛 itaigilo
itaigilo

🐛 jakivey32
jakivey32

🐛 jbennett2091
jbennett2091

🐛 jcamerin
jcamerin

🐛 jkeener1
jkeener1

🐛 jmetertea
jmetertea

🐛 - johnra2
johnra2

💻 + johnra2
johnra2

💻 johnzhao9
johnzhao9

🐛 josemanuelrolon
josemanuelrolon

💻 🐛 kabroxiko
kabroxiko

💻 🐛 karthikaiyasamy
karthikaiyasamy

📖 karwer
karwer

🐛 kaulonline
kaulonline

🐛 - kdaemonv
kdaemonv

🐛 + kdaemonv
kdaemonv

🐛 kdebski85
kdebski85

🐛 💻 kenji21
kenji21

💻 🐛 kfranic
kfranic

🐛 khalidkh
khalidkh

🐛 koalalam
koalalam

🐛 krzyk
krzyk

🐛 - lasselindqvist
lasselindqvist

🐛 + lasselindqvist
lasselindqvist

🐛 lgemeinhardt
lgemeinhardt

🐛 lihuaib
lihuaib

🐛 liqingjun123
liqingjun123

🐛 lonelyma1021
lonelyma1021

🐛 lpeddy
lpeddy

🐛 lujiefsi
lujiefsi

💻 - lukelukes
lukelukes

💻 + lukelukes
lukelukes

💻 lyriccoder
lyriccoder

🐛 marcelmore
marcelmore

🐛 matchbox
matchbox

🐛 matthiaskraaz
matthiaskraaz

🐛 meandonlyme
meandonlyme

🐛 mikesive
mikesive

🐛 - milossesic
milossesic

🐛 + milossesic
milossesic

🐛 mluckam
mluckam

💻 🐛 mohan-chinnappan-n
mohan-chinnappan-n

💻 mriddell95
mriddell95

🐛 mrlzh
mrlzh

🐛 msloan
msloan

🐛 mucharlaravalika
mucharlaravalika

🐛 - mvenneman
mvenneman

🐛 + mvenneman
mvenneman

🐛 nareshl119
nareshl119

🐛 nicolas-harraudeau-sonarsource
nicolas-harraudeau-sonarsource

🐛 noerremark
noerremark

🐛 novsirion
novsirion

🐛 nwcm
nwcm

📖 🐛 💻 oggboy
oggboy

🐛 - oinume
oinume

🐛 + oinume
oinume

🐛 orimarko
orimarko

💻 🐛 pablogomez2197
pablogomez2197

🐛 pacvz
pacvz

💻 pallavi agarwal
pallavi agarwal

🐛 parksungrin
parksungrin

🐛 patpatpat123
patpatpat123

🐛 - patriksevallius
patriksevallius

🐛 + patriksevallius
patriksevallius

🐛 pbrajesh1
pbrajesh1

🐛 phoenix384
phoenix384

🐛 piotrszymanski-sc
piotrszymanski-sc

💻 plan3d
plan3d

🐛 poojasix
poojasix

🐛 prabhushrikant
prabhushrikant

🐛 - pujitha8783
pujitha8783

🐛 + pujitha8783
pujitha8783

🐛 r-r-a-j
r-r-a-j

🐛 raghujayjunk
raghujayjunk

🐛 rajeshveera
rajeshveera

🐛 rajeswarreddy88
rajeswarreddy88

🐛 recdevs
recdevs

🐛 reudismam
reudismam

💻 🐛 - rijkt
rijkt

🐛 + rijkt
rijkt

🐛 rillig-tk
rillig-tk

🐛 rmohan20
rmohan20

💻 🐛 rnveach
rnveach

🐛 rxmicro
rxmicro

🐛 ryan-gustafson
ryan-gustafson

💻 🐛 sabi0
sabi0

🐛 - scais
scais

🐛 + scais
scais

🐛 schosin
schosin

🐛 screamingfrog
screamingfrog

💵 sebbASF
sebbASF

🐛 sergeygorbaty
sergeygorbaty

💻 shilko2013
shilko2013

🐛 shiomiyan
shiomiyan

📖 - simeonKondr
simeonKondr

🐛 + simeonKondr
simeonKondr

🐛 snajberk
snajberk

🐛 sniperrifle2004
sniperrifle2004

🐛 snuyanzin
snuyanzin

🐛 💻 soloturn
soloturn

🐛 soyodream
soyodream

🐛 sratz
sratz

🐛 - stonio
stonio

🐛 + stonio
stonio

🐛 sturton
sturton

💻 🐛 sudharmohan
sudharmohan

🐛 suruchidawar
suruchidawar

🐛 svenfinitiv
svenfinitiv

🐛 szymanp23
szymanp23

🐛 💻 tashiscool
tashiscool

🐛 - test-git-hook
test-git-hook

🐛 + test-git-hook
test-git-hook

🐛 testation21
testation21

💻 🐛 thanosa
thanosa

🐛 tiandiyixian
tiandiyixian

🐛 tobwoerk
tobwoerk

🐛 tprouvot
tprouvot

🐛 💻 trentchilders
trentchilders

🐛 - triandicAnt
triandicAnt

🐛 + triandicAnt
triandicAnt

🐛 trishul14
trishul14

🐛 tsui
tsui

🐛 wangzitom12306
wangzitom12306

🐛 winhkey
winhkey

🐛 witherspore
witherspore

🐛 wjljack
wjljack

🐛 - wuchiuwong
wuchiuwong

🐛 + wuchiuwong
wuchiuwong

🐛 xingsong
xingsong

🐛 xioayuge
xioayuge

🐛 xnYi9wRezm
xnYi9wRezm

💻 🐛 xuanuy
xuanuy

🐛 xyf0921
xyf0921

🐛 yalechen-cyw3
yalechen-cyw3

🐛 - yasuharu-sato
yasuharu-sato

🐛 + yasuharu-sato
yasuharu-sato

🐛 zenglian
zenglian

🐛 zgrzyt93
zgrzyt93

💻 🐛 zh3ng
zh3ng

🐛 zt_soft
zt_soft

🐛 ztt79
ztt79

🐛 zzzzfeng
zzzzfeng

🐛 - Árpád Magosányi
Árpád Magosányi

🐛 + Árpád Magosányi
Árpád Magosányi

🐛 任贵杰
任贵杰

🐛 + 天热吃西瓜
天热吃西瓜

🐛 茅延安
茅延安

💻 From 991bc2c41d92de4f9b18cfe67d63870fb9428a2e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 18:12:13 +0100 Subject: [PATCH 13/17] [apex] Report LexException when extracting comments --- .../pmd/lang/apex/ast/ApexCommentBuilder.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java index 48d41f0faa..7cc9e23f8d 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentBuilder.java @@ -14,10 +14,14 @@ import java.util.List; import java.util.Map; import java.util.RandomAccess; +import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; import org.antlr.v4.runtime.Token; import net.sourceforge.pmd.annotation.InternalApi; +import net.sourceforge.pmd.lang.ast.LexException; import net.sourceforge.pmd.lang.document.TextDocument; import net.sourceforge.pmd.lang.document.TextRegion; @@ -106,6 +110,13 @@ final class ApexCommentBuilder { private static CommentInformation extractInformationFromComments(TextDocument sourceCode, String suppressMarker) { String source = sourceCode.getText().toString(); ApexLexer lexer = new ApexLexer(new CaseInsensitiveInputStream(CharStreams.fromString(source))); + lexer.removeErrorListeners(); + lexer.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + throw new LexException(line, charPositionInLine, sourceCode.getFileId(), msg, e); + } + }); List allCommentTokens = new ArrayList<>(); Map suppressMap = new HashMap<>(); From 509452577def03f1ae357722204424d0ff53591d Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 18:16:06 +0100 Subject: [PATCH 14/17] [apex] Add test case for #5333 --- .../sourceforge/pmd/lang/apex/ast/ApexCommentTest.java | 8 ++++++++ .../net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentTest.java index 728cce6253..6e847170bf 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexCommentTest.java @@ -66,4 +66,12 @@ class ApexCommentTest extends ApexParserTestBase { ASTFormalComment comment = file.descendants(ASTUserClass.class).children(ASTFormalComment.class).first(); assertEquals(FORMAL_COMMENT_CONTENT, comment.getImage()); } + + @Test + void fileWithUnicodeEscapes() { + ASTApexFile file = apex.parse(FORMAL_COMMENT_CONTENT + "\n" + + "class MyClass { String s = 'Fran\\u00E7ois'; }"); + ASTFormalComment comment = file.descendants(ASTUserClass.class).children(ASTFormalComment.class).first(); + assertEquals(FORMAL_COMMENT_CONTENT, comment.getImage()); + } } diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java index b075160370..22104ac401 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/ast/ApexLexerTest.java @@ -57,6 +57,7 @@ class ApexLexerTest { @Test void testLexerUnicodeEscapes() { String s = "'Fran\\u00E7ois'"; + // note: with apex-parser 4.3.1, no errors are reported anymore assertEquals(2, getLexingErrors(CharStreams.fromString(s))); assertEquals(0, getLexingErrors(new CaseInsensitiveInputStream(CharStreams.fromString(s)))); } @@ -71,7 +72,7 @@ class ApexLexerTest { return errorListener.getErrorCount(); } - static class ErrorListener extends BaseErrorListener { + private static class ErrorListener extends BaseErrorListener { private int errorCount = 0; @Override From 093683bc592e968ae629f7087655575efd394c92 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 18:17:49 +0100 Subject: [PATCH 15/17] [doc] Update release notes (#5284, #5333) --- docs/pages/release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 5fa3ac04b6..4a522f9532 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -17,6 +17,8 @@ This is a {{ site.pmd.release_type }} release. ### 🐛 Fixed Issues * ant * [#1860](https://github.com/pmd/pmd/issues/1860): \[ant] Reflective access warnings on java > 9 and java < 17 +* apex + * [#5333](https://github.com/pmd/pmd/issues/5333): \[apex] Token recognition errors for string containing unicode escape sequence * java * [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads * [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas @@ -29,6 +31,7 @@ This is a {{ site.pmd.release_type }} release. instead (note different package `ast` instead of `antlr4`). ### ✨ External Contributions +* [#5284](https://github.com/pmd/pmd/pull/5284): \[apex] Use case-insensitive input stream to avoid choking on Unicode escape sequences - [Willem A. Hajenius](https://github.com/wahajenius) (@wahajenius) {% endtocmaker %} From e1d4f27e198beba891a3b4d20e112956229c6e4a Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 18:18:06 +0100 Subject: [PATCH 16/17] Add @wahajenius as a contributor --- .all-contributorsrc | 9 + docs/pages/pmd/projectdocs/credits.md | 234 +++++++++++++------------- 2 files changed, 127 insertions(+), 116 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 95ebc05d6e..3ccf2e8784 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -7865,6 +7865,15 @@ "contributions": [ "code" ] + }, + { + "login": "wahajenius", + "name": "Willem A. Hajenius", + "avatar_url": "https://avatars.githubusercontent.com/u/7836322?v=4", + "profile": "https://github.com/wahajenius", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/docs/pages/pmd/projectdocs/credits.md b/docs/pages/pmd/projectdocs/credits.md index 9497ea7378..8bedbc0f63 100644 --- a/docs/pages/pmd/projectdocs/credits.md +++ b/docs/pages/pmd/projectdocs/credits.md @@ -350,769 +350,771 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d JJengility
JJengility

🐛 Jake Hemmerle
Jake Hemmerle

🐛 + Jakub Dupak
Jakub Dupak

💻 James Harrison
James Harrison

🐛 💻 Jamie Bisotti
Jamie Bisotti

🐛 Jan
Jan

🐛 Jan Aertgeerts
Jan Aertgeerts

💻 🐛 - Jan Brümmer
Jan Brümmer

🐛 + Jan Brümmer
Jan Brümmer

🐛 Jan Tříska
Jan Tříska

🐛 Jan-Lukas Else
Jan-Lukas Else

🐛 Jason Qiu
Jason Qiu

💻 📖 Jason Williams
Jason Williams

🐛 Javier Spagnoletti
Javier Spagnoletti

🐛 Jean-Paul Mayer
Jean-Paul Mayer

🐛 - Jean-Simon Larochelle
Jean-Simon Larochelle

🐛 + Jean-Simon Larochelle
Jean-Simon Larochelle

🐛 Jeff Bartolotta
Jeff Bartolotta

💻 🐛 Jeff Hube
Jeff Hube

💻 🐛 Jeff Jensen
Jeff Jensen

🐛 Jeff May
Jeff May

🐛 Jens Gerdes
Jens Gerdes

🐛 Jeroen Borgers
Jeroen Borgers

🐛 💻 📢 - Jeroen Meijer
Jeroen Meijer

🐛 + Jeroen Meijer
Jeroen Meijer

🐛 Jeroen van Wilgenburg
Jeroen van Wilgenburg

📖 Jerome Russ
Jerome Russ

🐛 JerritEic
JerritEic

💻 📖 🐛 Jiri Pejchal
Jiri Pejchal

🐛 Jithin Sunny
Jithin Sunny

🐛 Jiří Škorpil
Jiří Škorpil

🐛 - Joao Machado
Joao Machado

🐛 + Joao Machado
Joao Machado

🐛 Jochen Krauss
Jochen Krauss

🐛 Johan Hammar
Johan Hammar

🐛 John Karp
John Karp

🐛 John Zhang
John Zhang

🐛 John-Teng
John-Teng

💻 🐛 Jon Moroney
Jon Moroney

💻 🐛 - Jonas Geiregat
Jonas Geiregat

🐛 + Jonas Geiregat
Jonas Geiregat

🐛 Jonas Keßler
Jonas Keßler

🐛 Jonathan Wiesel
Jonathan Wiesel

💻 🐛 Jordan
Jordan

🐛 Jordi Llach
Jordi Llach

🐛 Jorge Solórzano
Jorge Solórzano

🐛 JorneVL
JorneVL

🐛 - Jose Palafox
Jose Palafox

🐛 + Jose Palafox
Jose Palafox

🐛 Jose Stovall
Jose Stovall

🐛 Joseph
Joseph

💻 Joseph Heenan
Joseph Heenan

🐛 Josh Feingold
Josh Feingold

💻 🐛 Josh Holthaus
Josh Holthaus

🐛 Joshua S Arquilevich
Joshua S Arquilevich

🐛 - João Dinis Ferreira
João Dinis Ferreira

📖 + João Dinis Ferreira
João Dinis Ferreira

📖 João Ferreira
João Ferreira

💻 🐛 João Pedro Schmitt
João Pedro Schmitt

🐛 Juan Martín Sotuyo Dodero
Juan Martín Sotuyo Dodero

💻 📖 🐛 🚧 Juan Pablo Civile
Juan Pablo Civile

🐛 Julian Voronetsky
Julian Voronetsky

🐛 Julien
Julien

🐛 - Julius
Julius

🐛 + Julius
Julius

🐛 JustPRV
JustPRV

🐛 Justin Stroud
Justin Stroud

💻 Jörn Huxhorn
Jörn Huxhorn

🐛 KThompso
KThompso

🐛 Kai Amundsen
Kai Amundsen

🐛 Karel Vervaeke
Karel Vervaeke

🐛 - Karl-Andero Mere
Karl-Andero Mere

🐛 + Karl-Andero Mere
Karl-Andero Mere

🐛 Karl-Philipp Richter
Karl-Philipp Richter

🐛 Karsten Silz
Karsten Silz

🐛 Kazuma Watanabe
Kazuma Watanabe

🐛 Kev
Kev

🐛 Keve Müller
Keve Müller

🐛 Kevin Guerra
Kevin Guerra

💻 - Kevin Jones
Kevin Jones

🐛 💻 + Kevin Jones
Kevin Jones

🐛 💻 Kevin Poorman
Kevin Poorman

🐛 Kevin Wayne
Kevin Wayne

🐛 Kieran Black
Kieran Black

🐛 Kirill Zubov
Kirill Zubov

🐛 Kirk Clemens
Kirk Clemens

💻 🐛 Klaus Hartl
Klaus Hartl

🐛 - Koen Van Looveren
Koen Van Looveren

🐛 + Koen Van Looveren
Koen Van Looveren

🐛 Kris Scheibe
Kris Scheibe

💻 🐛 Krystian Dabrowski
Krystian Dabrowski

🐛 💻 Kunal Thanki
Kunal Thanki

🐛 LaLucid
LaLucid

💻 Larry Diamond
Larry Diamond

💻 🐛 Lars Knickrehm
Lars Knickrehm

🐛 - Laurent Bovet
Laurent Bovet

🐛 💻 + Laurent Bovet
Laurent Bovet

🐛 💻 Leo Gutierrez
Leo Gutierrez

🐛 LiGaOg
LiGaOg

💻 Liam Sharp
Liam Sharp

🐛 Lintsi
Lintsi

🐛 Linus Fernandes
Linus Fernandes

🐛 Lixon Lookose
Lixon Lookose

🐛 - Logesh
Logesh

🐛 + Logesh
Logesh

🐛 Lorenzo Gabriele
Lorenzo Gabriele

🐛 Loïc Ledoyen
Loïc Ledoyen

🐛 Lucas
Lucas

🐛 Lucas Silva
Lucas Silva

🐛 Lucas Soncini
Lucas Soncini

💻 🐛 Luis Alcantar
Luis Alcantar

💻 - Lukas Gräf
Lukas Gräf

💻 + Lukas Gräf
Lukas Gräf

💻 Lukasz Slonina
Lukasz Slonina

🐛 Lukebray
Lukebray

🐛 Lynn
Lynn

💻 🐛 Lyor Goldstein
Lyor Goldstein

🐛 MCMicS
MCMicS

🐛 Macarse
Macarse

🐛 - Machine account for PMD
Machine account for PMD

💻 + Machine account for PMD
Machine account for PMD

💻 Maciek Siemczyk
Maciek Siemczyk

🐛 Maikel Steneker
Maikel Steneker

💻 🐛 Maksim Moiseikin
Maksim Moiseikin

🐛 Manfred Koch
Manfred Koch

🐛 Manuel Moya Ferrer
Manuel Moya Ferrer

💻 🐛 Manuel Ryan
Manuel Ryan

🐛 - Marat Vyshegorodtsev
Marat Vyshegorodtsev

🐛 + Marat Vyshegorodtsev
Marat Vyshegorodtsev

🐛 Marcel Härle
Marcel Härle

🐛 Marcello Fialho
Marcello Fialho

🐛 Marcin Dąbrowski
Marcin Dąbrowski

💻 Marcin Rataj
Marcin Rataj

🐛 Marcono1234
Marcono1234

🐛 Mark Adamcin
Mark Adamcin

🐛 - Mark Hall
Mark Hall

💻 🐛 + Mark Hall
Mark Hall

💻 🐛 Mark Kolich
Mark Kolich

🐛 Mark Pritchard
Mark Pritchard

🐛 Markus Rathgeb
Markus Rathgeb

🐛 Marquis Wang
Marquis Wang

🐛 MartGit
MartGit

🐛 Martin Feldsztejn
Martin Feldsztejn

🐛 - Martin Lehmann
Martin Lehmann

🐛 + Martin Lehmann
Martin Lehmann

🐛 Martin Spamer
Martin Spamer

🐛 Martin Tarjányi
Martin Tarjányi

🐛 MatFl
MatFl

🐛 Mateusz Stefanski
Mateusz Stefanski

🐛 Mathieu Gouin
Mathieu Gouin

🐛 MatiasComercio
MatiasComercio

💻 🐛 - Matt Benson
Matt Benson

🐛 + Matt Benson
Matt Benson

🐛 Matt De Poorter
Matt De Poorter

🐛 Matt Hargett
Matt Hargett

💻 💵 Matt Harrah
Matt Harrah

🐛 Matt Nelson
Matt Nelson

🐛 Matthew Amos
Matthew Amos

🐛 Matthew Duggan
Matthew Duggan

🐛 - Matthew Hall
Matthew Hall

🐛 + Matthew Hall
Matthew Hall

🐛 Matthew Rossner
Matthew Rossner

🐛 Matías Fraga
Matías Fraga

💻 🐛 Maxime Robert
Maxime Robert

💻 🐛 MetaBF
MetaBF

🐛 Metin Dagcilar
Metin Dagcilar

🐛 Michael
Michael

🐛 - Michael Bell
Michael Bell

🐛 + Michael Bell
Michael Bell

🐛 Michael Bernstein
Michael Bernstein

🐛 Michael Clay
Michael Clay

🐛 Michael Dombrowski
Michael Dombrowski

🐛 Michael Hausegger
Michael Hausegger

🐛 Michael Hoefer
Michael Hoefer

🐛 Michael Kolesnikov
Michael Kolesnikov

🐛 - Michael Möbius
Michael Möbius

🐛 + Michael Möbius
Michael Möbius

🐛 Michael N. Lipp
Michael N. Lipp

🐛 Michael Pellegrini
Michael Pellegrini

🐛 Michal Kordas
Michal Kordas

🐛 Michał Borek
Michał Borek

🐛 Michał Kuliński
Michał Kuliński

🐛 Miguel Núñez Díaz-Montes
Miguel Núñez Díaz-Montes

🐛 - Mihai Ionut
Mihai Ionut

🐛 + Mihai Ionut
Mihai Ionut

🐛 Mikhail Kuchma
Mikhail Kuchma

🐛 Mirek Hankus
Mirek Hankus

🐛 Mitch Spano
Mitch Spano

🐛 Mladjan Gadzic
Mladjan Gadzic

🐛 MrAngry52
MrAngry52

🐛 Muminur Choudhury
Muminur Choudhury

🐛 - Mykhailo Palahuta
Mykhailo Palahuta

💻 🐛 + Mykhailo Palahuta
Mykhailo Palahuta

💻 🐛 Nagendra Kumar Singh
Nagendra Kumar Singh

🐛 Nahuel Barrios
Nahuel Barrios

🐛 Nakul Sharma
Nakul Sharma

🐛 Nathan Braun
Nathan Braun

🐛 Nathan Reynolds
Nathan Reynolds

🐛 Nathan Reynolds
Nathan Reynolds

🐛 - Nathanaël
Nathanaël

🐛 + Nathanaël
Nathanaël

🐛 Naveen
Naveen

💻 Nazdravi
Nazdravi

🐛 Neha-Dhonde
Neha-Dhonde

🐛 Nicholas Doyle
Nicholas Doyle

🐛 Nick Butcher
Nick Butcher

🐛 Nico Gallinal
Nico Gallinal

🐛 - Nicola Dal Maso
Nicola Dal Maso

🐛 + Nicola Dal Maso
Nicola Dal Maso

🐛 Nicolas Filotto
Nicolas Filotto

💻 Nicolas Vervelle
Nicolas Vervelle

🐛 Nicolas Vuillamy
Nicolas Vuillamy

📖 Nikita Chursin
Nikita Chursin

🐛 Niklas Baudy
Niklas Baudy

🐛 Nikolas Havrikov
Nikolas Havrikov

🐛 - Nilesh Virkar
Nilesh Virkar

🐛 + Nilesh Virkar
Nilesh Virkar

🐛 Nimit Patel
Nimit Patel

🐛 Niranjan Harpale
Niranjan Harpale

🐛 Nirvik Patel
Nirvik Patel

💻 Noah Sussman
Noah Sussman

🐛 Noah0120
Noah0120

🐛 Noam Tamim
Noam Tamim

🐛 - Noel Grandin
Noel Grandin

🐛 + Noel Grandin
Noel Grandin

🐛 Olaf Haalstra
Olaf Haalstra

🐛 Oleg Andreych
Oleg Andreych

💻 🐛 Oleg Pavlenko
Oleg Pavlenko

🐛 Oleksii Dykov
Oleksii Dykov

💻 🐛 Oliver Eikemeier
Oliver Eikemeier

🐛 Oliver Siegmar
Oliver Siegmar

💵 - Olivier Parent
Olivier Parent

💻 🐛 + Olivier Parent
Olivier Parent

💻 🐛 Ollie Abbey
Ollie Abbey

💻 🐛 Ondrej Kratochvil
Ondrej Kratochvil

🐛 OverDrone
OverDrone

🐛 Ozan Gulle
Ozan Gulle

💻 🐛 PUNEET JAIN
PUNEET JAIN

🐛 Parbati Bose
Parbati Bose

🐛 - Paul Berg
Paul Berg

🐛 + Paul Berg
Paul Berg

🐛 Paul Guyot
Paul Guyot

💻 Pavel Bludov
Pavel Bludov

🐛 Pavel Mička
Pavel Mička

🐛 Pedro Nuno Santos
Pedro Nuno Santos

🐛 Pedro Rijo
Pedro Rijo

🐛 Pelisse Romain
Pelisse Romain

💻 📖 🐛 - Per Abich
Per Abich

💻 + Per Abich
Per Abich

💻 Pete Davids
Pete Davids

🐛 Peter Bruin
Peter Bruin

🐛 Peter Chittum
Peter Chittum

💻 🐛 Peter Cudmore
Peter Cudmore

🐛 Peter Kasson
Peter Kasson

🐛 Peter Kofler
Peter Kofler

🐛 - Peter Paul Bakker
Peter Paul Bakker

💻 + Peter Paul Bakker
Peter Paul Bakker

💻 Peter Rader
Peter Rader

🐛 Pham Hai Trung
Pham Hai Trung

🐛 Philip Graf
Philip Graf

💻 🐛 Philip Hachey
Philip Hachey

🐛 Philippe Ozil
Philippe Ozil

🐛 Phinehas Artemix
Phinehas Artemix

🐛 - Phokham Nonava
Phokham Nonava

🐛 + Phokham Nonava
Phokham Nonava

🐛 Pim van der Loos
Pim van der Loos

💻 ⚠️ Piotr Szymański
Piotr Szymański

🐛 Piotrek Żygieło
Piotrek Żygieło

💻 🐛 📖 Pranay Jaiswal
Pranay Jaiswal

🐛 Prasad Kamath
Prasad Kamath

🐛 Prasanna
Prasanna

🐛 - Presh-AR
Presh-AR

🐛 + Presh-AR
Presh-AR

🐛 Puneet1726
Puneet1726

🐛 RBRi
RBRi

🐛 Rafael Cortês
Rafael Cortês

🐛 RaheemShaik999
RaheemShaik999

🐛 RajeshR
RajeshR

💻 🐛 Ramachandra Mohan
Ramachandra Mohan

🐛 - Ramel0921
Ramel0921

🐛 + Ramel0921
Ramel0921

🐛 Raquel Pau
Raquel Pau

🐛 Ravikiran Janardhana
Ravikiran Janardhana

🐛 Reda Benhemmouche
Reda Benhemmouche

🐛 Reinhard Schiedermeier
Reinhard Schiedermeier

🐛 Renato Oliveira
Renato Oliveira

💻 🐛 Rich DiCroce
Rich DiCroce

🐛 - Richard Corfield
Richard Corfield

💻 + Richard Corfield
Richard Corfield

💻 Richard Corfield
Richard Corfield

🐛 💻 Riot R1cket
Riot R1cket

🐛 Rishabh Jain
Rishabh Jain

🐛 RishabhDeep Singh
RishabhDeep Singh

🐛 Rob Baillie
Rob Baillie

🐛 Robbie Martinus
Robbie Martinus

💻 🐛 - Robert Henry
Robert Henry

🐛 + Robert Henry
Robert Henry

🐛 Robert Mihaly
Robert Mihaly

🐛 Robert Painsi
Robert Painsi

🐛 Robert Russell
Robert Russell

🐛 Robert Sösemann
Robert Sösemann

💻 📖 📢 🐛 Robert Whitebit
Robert Whitebit

🐛 Robin Richtsfeld
Robin Richtsfeld

🐛 - Robin Stocker
Robin Stocker

💻 🐛 + Robin Stocker
Robin Stocker

💻 🐛 Robin Wils
Robin Wils

🐛 RochusOest
RochusOest

🐛 Rodolfo Noviski
Rodolfo Noviski

🐛 Rodrigo Casara
Rodrigo Casara

🐛 Rodrigo Fernandes
Rodrigo Fernandes

🐛 Roman Salvador
Roman Salvador

💻 🐛 - Ronald Blaschke
Ronald Blaschke

🐛 + Ronald Blaschke
Ronald Blaschke

🐛 Róbert Papp
Róbert Papp

🐛 Saikat Sengupta
Saikat Sengupta

🐛 Saksham Handu
Saksham Handu

🐛 Saladoc
Saladoc

🐛 Salesforce Bob Lightning
Salesforce Bob Lightning

🐛 Sam Carlberg
Sam Carlberg

🐛 - Sascha Riemer
Sascha Riemer

🐛 + Sascha Riemer
Sascha Riemer

🐛 Sashko
Sashko

💻 Satoshi Kubo
Satoshi Kubo

🐛 Scott Kennedy
Scott Kennedy

🐛 Scott Wells
Scott Wells

🐛 💻 Scrates1
Scrates1

🐛 💻 Scrsloota
Scrsloota

💻 - Sebastian Bögl
Sebastian Bögl

🐛 + Sebastian Bögl
Sebastian Bögl

🐛 Sebastian Davids
Sebastian Davids

🐛 Sebastian Schuberth
Sebastian Schuberth

🐛 Sebastian Schwarz
Sebastian Schwarz

🐛 Seren
Seren

🐛 💻 Sergey Gorbaty
Sergey Gorbaty

🐛 Sergey Kozlov
Sergey Kozlov

🐛 - Sergey Yanzin
Sergey Yanzin

💻 🐛 + Sergey Yanzin
Sergey Yanzin

💻 🐛 Seth Wilcox
Seth Wilcox

💻 Shai Bennathan
Shai Bennathan

🐛 💻 Shubham
Shubham

💻 🐛 Simon Abykov
Simon Abykov

💻 🐛 Simon Xiao
Simon Xiao

🐛 Srinivasan Venkatachalam
Srinivasan Venkatachalam

🐛 - Stanislav Gromov
Stanislav Gromov

🐛 + Stanislav Gromov
Stanislav Gromov

🐛 Stanislav Myachenkov
Stanislav Myachenkov

💻 Stefan Birkner
Stefan Birkner

🐛 Stefan Bohn
Stefan Bohn

🐛 Stefan Endrullis
Stefan Endrullis

🐛 Stefan Klöss-Schuster
Stefan Klöss-Schuster

🐛 Stefan Wolf
Stefan Wolf

🐛 - Stephan H. Wissel
Stephan H. Wissel

🐛 + Stephan H. Wissel
Stephan H. Wissel

🐛 Stephen
Stephen

🐛 Stephen Carter
Stephen Carter

🐛 Stephen Friedrich
Stephen Friedrich

🐛 Steve Babula
Steve Babula

💻 Steven Stearns
Steven Stearns

🐛 💻 Stexxe
Stexxe

🐛 - Stian Lågstad
Stian Lågstad

🐛 + Stian Lågstad
Stian Lågstad

🐛 StuartClayton5
StuartClayton5

🐛 Supun Arunoda
Supun Arunoda

🐛 Suren Abrahamyan
Suren Abrahamyan

🐛 Suvashri
Suvashri

📖 SwatiBGupta1110
SwatiBGupta1110

🐛 SyedThoufich
SyedThoufich

🐛 - Szymon Sasin
Szymon Sasin

🐛 + Szymon Sasin
Szymon Sasin

🐛 T-chuangxin
T-chuangxin

🐛 TERAI Atsuhiro
TERAI Atsuhiro

🐛 TIOBE Software
TIOBE Software

💻 🐛 Tarush Singh
Tarush Singh

💻 Taylor Smock
Taylor Smock

🐛 Techeira Damián
Techeira Damián

💻 🐛 - Ted Husted
Ted Husted

🐛 + Ted Husted
Ted Husted

🐛 TehBakker
TehBakker

🐛 The Gitter Badger
The Gitter Badger

🐛 Theodoor
Theodoor

🐛 Thiago Henrique Hüpner
Thiago Henrique Hüpner

🐛 Thibault Meyer
Thibault Meyer

🐛 Thomas Güttler
Thomas Güttler

🐛 - Thomas Jones-Low
Thomas Jones-Low

🐛 + Thomas Jones-Low
Thomas Jones-Low

🐛 Thomas Smith
Thomas Smith

💻 🐛 ThrawnCA
ThrawnCA

🐛 Thu Vo
Thu Vo

🐛 Thunderforge
Thunderforge

💻 🐛 Tim van der Lippe
Tim van der Lippe

🐛 Tobias Weimer
Tobias Weimer

💻 🐛 - Tom Copeland
Tom Copeland

🐛 💻 📖 + Tom Copeland
Tom Copeland

🐛 💻 📖 Tom Daly
Tom Daly

🐛 Tomas
Tomas

🐛 Tomer Figenblat
Tomer Figenblat

🐛 Tomi De Lucca
Tomi De Lucca

💻 🐛 Tony
Tony

📖 Torsten Kleiber
Torsten Kleiber

🐛 - TrackerSB
TrackerSB

🐛 + TrackerSB
TrackerSB

🐛 Tyson Stewart
Tyson Stewart

🐛 Ullrich Hafner
Ullrich Hafner

🐛 Utku Cuhadaroglu
Utku Cuhadaroglu

💻 🐛 Valentin Brandl
Valentin Brandl

🐛 Valeria
Valeria

🐛 Valery Yatsynovich
Valery Yatsynovich

📖 - Vasily Anisimov
Vasily Anisimov

🐛 + Vasily Anisimov
Vasily Anisimov

🐛 Vedant Chokshi
Vedant Chokshi

🐛 Vibhor Goyal
Vibhor Goyal

🐛 Vickenty Fesunov
Vickenty Fesunov

🐛 Victor Noël
Victor Noël

🐛 Vincent Galloy
Vincent Galloy

💻 Vincent HUYNH
Vincent HUYNH

🐛 - Vincent Maurin
Vincent Maurin

🐛 + Vincent Maurin
Vincent Maurin

🐛 Vincent Privat
Vincent Privat

🐛 Vishhwas
Vishhwas

🐛 Vishv_Android
Vishv_Android

🐛 Vitaly
Vitaly

🐛 Vitaly Polonetsky
Vitaly Polonetsky

🐛 Vojtech Polivka
Vojtech Polivka

🐛 - Vsevolod Zholobov
Vsevolod Zholobov

🐛 + Vsevolod Zholobov
Vsevolod Zholobov

🐛 Vyom Yadav
Vyom Yadav

💻 Wang Shidong
Wang Shidong

🐛 Waqas Ahmed
Waqas Ahmed

🐛 Wayne J. Earl
Wayne J. Earl

🐛 Wchenghui
Wchenghui

🐛 Wener
Wener

💻 - Will Winder
Will Winder

🐛 + Will Winder
Will Winder

🐛 + Willem A. Hajenius
Willem A. Hajenius

💻 William Brockhus
William Brockhus

💻 🐛 Wilson Kurniawan
Wilson Kurniawan

🐛 Wim Deblauwe
Wim Deblauwe

🐛 Woongsik Choi
Woongsik Choi

🐛 XenoAmess
XenoAmess

💻 🐛 - Yang
Yang

💻 - YaroslavTER
YaroslavTER

🐛 + Yang
Yang

💻 + YaroslavTER
YaroslavTER

🐛 Yasar Shaikh
Yasar Shaikh

💻 Young Chan
Young Chan

💻 🐛 YuJin Kim
YuJin Kim

🐛 Yuri Dolzhenko
Yuri Dolzhenko

🐛 Yurii Dubinka
Yurii Dubinka

🐛 - Zoltan Farkas
Zoltan Farkas

🐛 - Zustin
Zustin

🐛 + Zoltan Farkas
Zoltan Farkas

🐛 + Zustin
Zustin

🐛 aaronhurst-google
aaronhurst-google

🐛 💻 alexmodis
alexmodis

🐛 andreoss
andreoss

🐛 andrey81inmd
andrey81inmd

💻 🐛 anicoara
anicoara

🐛 - arunprasathav
arunprasathav

🐛 - asiercamara
asiercamara

🐛 + arunprasathav
arunprasathav

🐛 + asiercamara
asiercamara

🐛 astillich-igniti
astillich-igniti

💻 avesolovksyy
avesolovksyy

🐛 avishvat
avishvat

🐛 avivmu
avivmu

🐛 axelbarfod1
axelbarfod1

🐛 - b-3-n
b-3-n

🐛 - balbhadra9
balbhadra9

🐛 + b-3-n
b-3-n

🐛 + balbhadra9
balbhadra9

🐛 base23de
base23de

🐛 bergander
bergander

🐛 💻 berkam
berkam

💻 🐛 breizh31
breizh31

🐛 caesarkim
caesarkim

🐛 - carolyujing
carolyujing

🐛 - cbfiddle
cbfiddle

🐛 + carolyujing
carolyujing

🐛 + cbfiddle
cbfiddle

🐛 cesares-basilico
cesares-basilico

🐛 chrite
chrite

🐛 ciufudean
ciufudean

📖 cobratbq
cobratbq

🐛 coladict
coladict

🐛 - cosmoJFH
cosmoJFH

🐛 - cristalp
cristalp

🐛 + cosmoJFH
cosmoJFH

🐛 + cristalp
cristalp

🐛 crunsk
crunsk

🐛 cwholmes
cwholmes

🐛 cyberjj999
cyberjj999

🐛 cyw3
cyw3

🐛 📖 d1ss0nanz
d1ss0nanz

🐛 - dague1
dague1

📖 - dalizi007
dalizi007

💻 + dague1
dague1

📖 + dalizi007
dalizi007

💻 danbrycefairsailcom
danbrycefairsailcom

🐛 dariansanity
dariansanity

🐛 darrenmiliband
darrenmiliband

🐛 davidburstrom
davidburstrom

🐛 dbirkman-paloalto
dbirkman-paloalto

🐛 - deepak-patra
deepak-patra

🐛 - dependabot[bot]
dependabot[bot]

💻 🐛 + deepak-patra
deepak-patra

🐛 + dependabot[bot]
dependabot[bot]

💻 🐛 dinesh150
dinesh150

🐛 diziaq
diziaq

🐛 dreaminpast123
dreaminpast123

🐛 duanyanan
duanyanan

🐛 dutt-sanjay
dutt-sanjay

🐛 - duursma
duursma

💻 - dylanleung
dylanleung

🐛 + duursma
duursma

💻 + dylanleung
dylanleung

🐛 dzeigler
dzeigler

🐛 eant60
eant60

🐛 ekkirala
ekkirala

🐛 emersonmoura
emersonmoura

🐛 emouty
emouty

💻 🐛 - eugenepugach
eugenepugach

🐛 - fairy
fairy

🐛 + eugenepugach
eugenepugach

🐛 + fairy
fairy

🐛 filiprafalowicz
filiprafalowicz

💻 flxbl-io
flxbl-io

💵 foxmason
foxmason

🐛 frankegabor
frankegabor

🐛 frankl
frankl

🐛 - freafrea
freafrea

🐛 - fsapatin
fsapatin

🐛 + freafrea
freafrea

🐛 + fsapatin
fsapatin

🐛 gearsethenry
gearsethenry

🐛 gracia19
gracia19

🐛 gudzpoz
gudzpoz

🐛 guo fei
guo fei

🐛 gurmsc5
gurmsc5

🐛 - gwilymatgearset
gwilymatgearset

💻 🐛 - haigsn
haigsn

🐛 + gwilymatgearset
gwilymatgearset

💻 🐛 + haigsn
haigsn

🐛 hemanshu070
hemanshu070

🐛 henrik242
henrik242

🐛 hongpuwu
hongpuwu

🐛 hvbtup
hvbtup

💻 🐛 igniti GmbH
igniti GmbH

🐛 - ilovezfs
ilovezfs

🐛 - imax-erik
imax-erik

🐛 + ilovezfs
ilovezfs

🐛 + imax-erik
imax-erik

🐛 itaigilo
itaigilo

🐛 jakivey32
jakivey32

🐛 jbennett2091
jbennett2091

🐛 jcamerin
jcamerin

🐛 jkeener1
jkeener1

🐛 - jmetertea
jmetertea

🐛 - johnra2
johnra2

💻 + jmetertea
jmetertea

🐛 + johnra2
johnra2

💻 johnzhao9
johnzhao9

🐛 josemanuelrolon
josemanuelrolon

💻 🐛 kabroxiko
kabroxiko

💻 🐛 karthikaiyasamy
karthikaiyasamy

📖 karwer
karwer

🐛 - kaulonline
kaulonline

🐛 - kdaemonv
kdaemonv

🐛 + kaulonline
kaulonline

🐛 + kdaemonv
kdaemonv

🐛 kdebski85
kdebski85

🐛 💻 kenji21
kenji21

💻 🐛 kfranic
kfranic

🐛 khalidkh
khalidkh

🐛 koalalam
koalalam

🐛 - krzyk
krzyk

🐛 - lasselindqvist
lasselindqvist

🐛 + krzyk
krzyk

🐛 + lasselindqvist
lasselindqvist

🐛 lgemeinhardt
lgemeinhardt

🐛 lihuaib
lihuaib

🐛 liqingjun123
liqingjun123

🐛 lonelyma1021
lonelyma1021

🐛 lpeddy
lpeddy

🐛 - lujiefsi
lujiefsi

💻 - lukelukes
lukelukes

💻 + lujiefsi
lujiefsi

💻 + lukelukes
lukelukes

💻 lyriccoder
lyriccoder

🐛 marcelmore
marcelmore

🐛 matchbox
matchbox

🐛 matthiaskraaz
matthiaskraaz

🐛 meandonlyme
meandonlyme

🐛 - mikesive
mikesive

🐛 - milossesic
milossesic

🐛 + mikesive
mikesive

🐛 + milossesic
milossesic

🐛 mluckam
mluckam

💻 🐛 mohan-chinnappan-n
mohan-chinnappan-n

💻 mriddell95
mriddell95

🐛 mrlzh
mrlzh

🐛 msloan
msloan

🐛 - mucharlaravalika
mucharlaravalika

🐛 - mvenneman
mvenneman

🐛 + mucharlaravalika
mucharlaravalika

🐛 + mvenneman
mvenneman

🐛 nareshl119
nareshl119

🐛 nicolas-harraudeau-sonarsource
nicolas-harraudeau-sonarsource

🐛 noerremark
noerremark

🐛 novsirion
novsirion

🐛 nwcm
nwcm

📖 🐛 💻 - oggboy
oggboy

🐛 - oinume
oinume

🐛 + oggboy
oggboy

🐛 + oinume
oinume

🐛 orimarko
orimarko

💻 🐛 pablogomez2197
pablogomez2197

🐛 pacvz
pacvz

💻 pallavi agarwal
pallavi agarwal

🐛 parksungrin
parksungrin

🐛 - patpatpat123
patpatpat123

🐛 - patriksevallius
patriksevallius

🐛 + patpatpat123
patpatpat123

🐛 + patriksevallius
patriksevallius

🐛 pbrajesh1
pbrajesh1

🐛 phoenix384
phoenix384

🐛 piotrszymanski-sc
piotrszymanski-sc

💻 plan3d
plan3d

🐛 poojasix
poojasix

🐛 - prabhushrikant
prabhushrikant

🐛 - pujitha8783
pujitha8783

🐛 + prabhushrikant
prabhushrikant

🐛 + pujitha8783
pujitha8783

🐛 r-r-a-j
r-r-a-j

🐛 raghujayjunk
raghujayjunk

🐛 rajeshveera
rajeshveera

🐛 rajeswarreddy88
rajeswarreddy88

🐛 recdevs
recdevs

🐛 - reudismam
reudismam

💻 🐛 - rijkt
rijkt

🐛 + reudismam
reudismam

💻 🐛 + rijkt
rijkt

🐛 rillig-tk
rillig-tk

🐛 rmohan20
rmohan20

💻 🐛 rnveach
rnveach

🐛 rxmicro
rxmicro

🐛 ryan-gustafson
ryan-gustafson

💻 🐛 - sabi0
sabi0

🐛 - scais
scais

🐛 + sabi0
sabi0

🐛 + scais
scais

🐛 schosin
schosin

🐛 screamingfrog
screamingfrog

💵 sebbASF
sebbASF

🐛 sergeygorbaty
sergeygorbaty

💻 shilko2013
shilko2013

🐛 - shiomiyan
shiomiyan

📖 - simeonKondr
simeonKondr

🐛 + shiomiyan
shiomiyan

📖 + simeonKondr
simeonKondr

🐛 snajberk
snajberk

🐛 sniperrifle2004
sniperrifle2004

🐛 snuyanzin
snuyanzin

🐛 💻 soloturn
soloturn

🐛 soyodream
soyodream

🐛 - sratz
sratz

🐛 - stonio
stonio

🐛 + sratz
sratz

🐛 + stonio
stonio

🐛 sturton
sturton

💻 🐛 sudharmohan
sudharmohan

🐛 suruchidawar
suruchidawar

🐛 svenfinitiv
svenfinitiv

🐛 szymanp23
szymanp23

🐛 💻 - tashiscool
tashiscool

🐛 - test-git-hook
test-git-hook

🐛 + tashiscool
tashiscool

🐛 + test-git-hook
test-git-hook

🐛 testation21
testation21

💻 🐛 thanosa
thanosa

🐛 tiandiyixian
tiandiyixian

🐛 tobwoerk
tobwoerk

🐛 tprouvot
tprouvot

🐛 💻 - trentchilders
trentchilders

🐛 - triandicAnt
triandicAnt

🐛 + trentchilders
trentchilders

🐛 + triandicAnt
triandicAnt

🐛 trishul14
trishul14

🐛 tsui
tsui

🐛 wangzitom12306
wangzitom12306

🐛 winhkey
winhkey

🐛 witherspore
witherspore

🐛 - wjljack
wjljack

🐛 - wuchiuwong
wuchiuwong

🐛 + wjljack
wjljack

🐛 + wuchiuwong
wuchiuwong

🐛 xingsong
xingsong

🐛 xioayuge
xioayuge

🐛 xnYi9wRezm
xnYi9wRezm

💻 🐛 xuanuy
xuanuy

🐛 xyf0921
xyf0921

🐛 - yalechen-cyw3
yalechen-cyw3

🐛 - yasuharu-sato
yasuharu-sato

🐛 + yalechen-cyw3
yalechen-cyw3

🐛 + yasuharu-sato
yasuharu-sato

🐛 zenglian
zenglian

🐛 zgrzyt93
zgrzyt93

💻 🐛 zh3ng
zh3ng

🐛 zt_soft
zt_soft

🐛 ztt79
ztt79

🐛 - zzzzfeng
zzzzfeng

🐛 - Árpád Magosányi
Árpád Magosányi

🐛 + zzzzfeng
zzzzfeng

🐛 + Árpád Magosányi
Árpád Magosányi

🐛 任贵杰
任贵杰

🐛 茅延安
茅延安

💻 From 32f55e22e3df43e3442b8077752d404b2f18eea2 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Thu, 14 Nov 2024 19:18:11 +0100 Subject: [PATCH 17/17] [doc] Update release notes (#5329, #5330) --- docs/pages/release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 5fa3ac04b6..44f31cb3cc 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -20,6 +20,7 @@ This is a {{ site.pmd.release_type }} release. * java * [#5293](https://github.com/pmd/pmd/issues/5293): \[java] Deadlock when executing PMD in multiple threads * [#5324](https://github.com/pmd/pmd/issues/5324): \[java] Issue with type inference of nested lambdas + * [#5329](https://github.com/pmd/pmd/issues/5329): \[java] Type inference issue with unknown method ref in call chain ### 🚨 API Changes