Repository: hyperskill/hyperstyle (language: python)

Issue:
PMD rule AvoidDuplicateLiterals is not working correctly
https://hyperskill.org/learn/step/5530#solutions-859202

```java
class CinemaFacadeTestDrive {
    public static void main(String[] args) throws InterruptedException {
        PopcornPopper popcorn = new PopcornPopper();
        Lights lights = new Lights();
        Projector projector = new Projector();

        CinemaFacade cinemaFacade = new CinemaFacade(popcorn, lights, projector);

        cinemaFacade.watchMovie();
        System.out.println("We are watching a movie");
        Thread.sleep(5000);
        System.out.println("The End");
        cinemaFacade.endMovie();
    }
}

class CinemaFacade {
    private PopcornPopper popcorn;
    private Lights lights;
    private Projector projector;

    public CinemaFacade(PopcornPopper popcorn, Lights lights, Projector projector) {
        this.popcorn = popcorn;
        this.lights = lights;
        this.projector = projector;
    }

    public void watchMovie() {
        System.out.println("Get ready to watch a movie...");
        popcorn.on();
        popcorn.pop();
        lights.off();
        projector.on();
    }

    public void endMovie() {
        popcorn.off();
        lights.on();
        projector.off();
    }
}

class PopcornPopper {
    String description = "PopcornPopper";

    public void on() {
        System.out.println(description + " on");
    }

    public void off() {
        System.out.println(description + " off");
    }

    public void pop() {
        System.out.println(description + " popping popcorn!");
    }
}

class Projector {
    String description = "Projector";

    public void on() {
        System.out.println(description + " on");
    }

    public void off() {
        System.out.println(description + " off");
    }
}

class Lights {
    String description = "Lights";

    public void on() {
        System.out.println(description + " on");
    }

    public void off() {
        System.out.println(description + " off");
    }

    public void dim(int level) {
        System.out.println(description + " dimming to " + level + "%");
    }

    public String toString() {
        return description;
    }
}
```

Style error appears on line `System.out.println(description + " off");`:
The String " off" appears 3 times in the file

https://pmd.github.io/latest/pmd_rules_java_errorprone.html#avoidduplicateliterals

This rule should work if the string appears 4 or more times (maxDuplicateLiterals = 4) and is more than or equal to 3 characters in length (minimumLength = 3). And in the code, the lines `" on"` and `" off"` occur 3 times. But the rule only works on `" off"`. And it shouldn't work. If it should, then why does it not work on the "on" string?

Is there a bug or is everything working correctly?



Discussion / hints:
@meanmail Actually it's not AvoidDuplicateLiterals, but [MultipleStringLiterals](https://checkstyle.sourceforge.io/config_coding.html#MultipleStringLiterals) from Checkstyle. In `main` this rule has the following properties:
```xml
<module name="MultipleStringLiterals">
    <property name="allowedDuplicates" value="2"/>
    <property name="ignoreStringsRegexp" value="^.{1,5}$"/>
</module>
```

So, all strings of length 5 or less are ignored. But according to the documentation, the regexp for this rule must include quotes, which are not present in the current regexp. That's why Checkstyle ignores `" on"` (its length including quotes is 5). I'll fix this bug in `main-upd`.

Fix patch:
diff --git a/src/python/review/inspectors/checkstyle/files/config.xml b/src/python/review/inspectors/checkstyle/files/config.xml
index 92fa6f07..81fbc370 100644
--- a/src/python/review/inspectors/checkstyle/files/config.xml
+++ b/src/python/review/inspectors/checkstyle/files/config.xml
@@ -44,8 +44,9 @@
         <module name="MissingSwitchDefault"/>
         <module name="ModifiedControlVariable"/>
         <module name="MultipleStringLiterals">
-            <property name="allowedDuplicates" value="2"/>
-            <property name="ignoreStringsRegexp" value="^.{1,5}$"/>
+            <!-- Consistent with AvoidDuplicateLiterals from PMD -->
+            <property name="allowedDuplicates" value="3"/>
+            <property name="ignoreStringsRegexp" value='^".{0,2}"$'/>
         </module>
         <module name="MultipleVariableDeclarations"/>
         <module name="NoFinalizer"/>


Test patch:
diff --git a/test/python/inspectors/test_checkstyle_inspector.py b/test/python/inspectors/test_checkstyle_inspector.py
index ce7040aa..ac691ff6 100644
--- a/test/python/inspectors/test_checkstyle_inspector.py
+++ b/test/python/inspectors/test_checkstyle_inspector.py
@@ -43,6 +43,7 @@
     ('test_indentation_with_spaces.java', 0),
     ('test_indentation_with_tabs.java', 0),
     ('test_indentation_google_style.java', 4),
+    ('test_multiple_literals.java', 1),
 ]
 
 
diff --git a/test/python/inspectors/test_pmd_inspector.py b/test/python/inspectors/test_pmd_inspector.py
index 15b8006e..3702a79b 100644
--- a/test/python/inspectors/test_pmd_inspector.py
+++ b/test/python/inspectors/test_pmd_inspector.py
@@ -32,6 +32,7 @@
     ('test_valid_curly_braces.java', 0),
     ('test_when_only_equals_overridden.java', 1),
     ('test_valid_spaces.java', 0),
+    ('test_multiple_literals.java', 1),
 ]
 
 
diff --git a/test/resources/inspectors/java/test_multiple_literals.java b/test/resources/inspectors/java/test_multiple_literals.java
new file mode 100644
index 00000000..58a9e2ee
--- /dev/null
+++ b/test/resources/inspectors/java/test_multiple_literals.java
@@ -0,0 +1,32 @@
+class Main {
+    public static void main(String[] args) {
+        // ok
+        String shortRareLiteral1 = "12";
+        String shortRareLiteral2 = "12";
+        String shortRareLiteral3 = "12";
+
+        // ok
+        String longRareLiteral1 = "123";
+        String longRareLiteral2 = "123";
+        String longRareLiteral3 = "123";
+
+        // ok
+        String shortFrequentLiteral1 = "34";
+        String shortFrequentLiteral2 = "34";
+        String shortFrequentLiteral3 = "34";
+        String shortFrequentLiteral4 = "34";
+
+        // warning
+        String longFrequentLiteral1 = "456";
+        String longFrequentLiteral2 = "456";
+        String longFrequentLiteral3 = "456";
+        String longFrequentLiteral4 = "456";
+
+        System.out.println(
+            shortRareLiteral1 + shortRareLiteral2 + shortRareLiteral3 +
+            longRareLiteral1 + longRareLiteral2 + longRareLiteral3 +
+            shortFrequentLiteral1 + shortFrequentLiteral2 + shortFrequentLiteral3 + shortFrequentLiteral4 +
+            longFrequentLiteral1 + longFrequentLiteral2 + longFrequentLiteral3 + longFrequentLiteral4
+        );
+    }
+}