Repository: pmd/pmd (Java)

Issue:
[java] PackageCase: Suppression comment has no effect due to finding at wrong position in case of JavaDoc comment
**Affects PMD Version:** 7.9.0

**Rule:** [PackageCase](https://docs.pmd-code.org/latest/pmd_rules_java_codestyle.html#packagecase)

**Description:**

The `NOPMD` comment does not work correctly in PMD 7.9.0 if the line preceding is JavaDoc.

Maybe regression of #4939?

**Code Sample demonstrating the issue:**

```java
/**
*/
package foo.Bar; //NOPMD upper-case package name ok

public class Baz { }
```

**Steps to reproduce:**

PMD 7.8.0: OK, finding correctly suppressed: 
```
$ ./pmd-bin-7.8.0/bin/pmd check --rulesets=category/java/codestyle.xml/PackageCase -d foo --no-progress --no-cache
```

PMD 7.9.0: NOT OK, finding not correctly suppressed:
```
$ ./pmd-bin-7.9.0/bin/pmd check --rulesets=category/java/codestyle.xml/PackageCase -d foo --no-progress --no-cache
foo/Bar/Baz.java:1:     PackageCase:    Package name contains upper case characters
```

**Running PMD through:** *CLI | Ant | Maven | Gradle | Designer | Other*

<!-- If relevant, also include your JDK and OS information, e.g. for ClassNotFoundException, LinkageError, reflection failures, etc. -->



Discussion: I can confirm the same problem in https://github.com/dsldevkit/dsl-devkit/pull/1076



Fix (patch):
diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md
index e56f2b155bc..171681947b8 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
 * java-bestpractices
   * [#5369](https://github.com/pmd/pmd/issues/5369): \[java] UnusedPrivateMethod false positives with lombok.val
+* java-codestyle
+  * [#5452](https://github.com/pmd/pmd/issues/5452): \[java] Suppression comment has no effect due to finding at wrong position in case of JavaDoc comment
 
 ### 🚨 API Changes
 
diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java
index 046101921ec..40cf4b0f3bb 100644
--- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java
+++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/ast/ASTPackageDeclaration.java
@@ -4,6 +4,10 @@
 
 package net.sourceforge.pmd.lang.java.ast;
 
+import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
+import net.sourceforge.pmd.lang.document.FileLocation;
+import net.sourceforge.pmd.lang.document.TextRegion;
+
 /**
  * Package declaration at the top of a {@linkplain ASTCompilationUnit source file}.
  * Since 7.0, there is no Name node anymore. Use {@link #getName()} instead.
@@ -18,6 +22,8 @@
  */
 public final class ASTPackageDeclaration extends AbstractJavaNode implements Annotatable, ASTTopLevelDeclaration, JavadocCommentOwner {
 
+    private TextRegion reportRegion;
+
     ASTPackageDeclaration(int id) {
         super(id);
     }
@@ -28,6 +34,15 @@ protected <P, R> R acceptVisitor(JavaVisitor<? super P, ? extends R> visitor, P
         return visitor.visit(this, data);
     }
 
+    void setNameRegion(JavaccToken startTok, JavaccToken endTok) {
+        reportRegion = TextRegion.union(startTok.getRegion(), endTok.getRegion());
+    }
+
+    @Override
+    public FileLocation getReportLocation() {
+        // the report location is the name of the package
+        return getAstInfo().getTextDocument().toLocation(reportRegion);
+    }
 
     /**
      * Returns the name of the package.
diff --git a/pmd-java/src/main/javacc/Java.jjt b/pmd-java/src/main/javacc/Java.jjt
index 764d59d5204..87d1eacc1cc 100644
--- a/pmd-java/src/main/javacc/Java.jjt
+++ b/pmd-java/src/main/javacc/Java.jjt
@@ -1096,9 +1096,15 @@ private void ModuleDeclLahead() #void:
 
 
 void PackageDeclaration() :
-{String image;}
+{String image; JavaccToken startTok, endTok;}
 {
-  ModAnnotationList() "package" image=VoidName() { jjtThis.setImage(image); } ";"
+  ModAnnotationList() startTok="package"
+  image=VoidName() {
+    endTok = getToken(0);
+    jjtThis.setNameRegion(startTok.getNext(), endTok);
+    jjtThis.setImage(image);
+  }
+  ";"
 }
 
 void ImportDeclaration() :