• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pmd / pmd / 870

19 Oct 2026 02:29PM UTC coverage: 79.835% (+0.01%) from 79.825%
870

push

github

web-flow
[java] Prepare deprecation of asCtx in java-errorprone (part of #4814) (#7132)

#4814: prepare deprecation of asCtx in java-errorprone

Rewrite all rule visitors in java-codestyle to...
* cast the "Object data" parameter to RuleContext first
* never touch "data" again
* return null instead of data

20382 of 26564 branches covered (76.73%)

Branch coverage included in aggregate %.

123 of 127 new or added lines in 28 files covered. (96.85%)

43775 of 53798 relevant lines covered (81.37%)

0.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.26
/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/rule/errorprone/SuspiciousOctalEscapeRule.java
1
/*
2
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3
 */
4

5
package net.sourceforge.pmd.lang.java.rule.errorprone;
6

7
import net.sourceforge.pmd.lang.java.ast.ASTStringLiteral;
8
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRulechainRule;
9
import net.sourceforge.pmd.reporting.RuleContext;
10

11
public class SuspiciousOctalEscapeRule extends AbstractJavaRulechainRule {
12

13
    public SuspiciousOctalEscapeRule() {
14
        super(ASTStringLiteral.class);
1 ✔
15
    }
1 ✔
16

17
    @Override
18
    public Object visit(ASTStringLiteral node, Object data) {
19
        RuleContext ctx = (RuleContext) data;
1 ✔
20

21
        String image = node.getImage();
1 ✔
22
        // trim quotes
23
        String s = image.substring(1, image.length() - 1);
1 ✔
24

25
        // process escape sequences
26
        int offset = 0;
1 ✔
27
        for (int slash = s.indexOf('\\', offset); slash != -1
1 ✔
28
                && slash < s.length() - 1; slash = s.indexOf('\\', offset)) {
1 !
29
            String escapeSequence = s.substring(slash + 1);
1 ✔
30
            char first = escapeSequence.charAt(0);
1 ✔
31
            offset = slash + 1; // next offset - after slash
1 ✔
32

33
            if (isOctal(first)) {
1 ✔
34
                if (escapeSequence.length() > 1) {
1 !
35
                    char second = escapeSequence.charAt(1);
1 ✔
36
                    if (isOctal(second)) {
1 !
37
                        if (escapeSequence.length() > 2) {
1 !
38
                            char third = escapeSequence.charAt(2);
1 ✔
39
                            if (isOctal(third)) {
1 ✔
40
                                // this is either a three digit octal escape
41
                                // or a two-digit
42
                                // octal escape followed by an octal digit.
43
                                // the value of
44
                                // the first digit in the sequence
45
                                // determines which is the
46
                                // case
47
                                if (first != '0' && first != '1' && first != '2' && first != '3') {
1 !
48
                                    // VIOLATION: it's a two-digit octal
49
                                    // escape followed by
50
                                    // an octal digit -- legal but very
51
                                    // confusing!
52
                                    ctx.addViolation(node, "\\" + first + second + " + " + third);
1 ✔
53
                                } else {
54
                                    // if there is a 4th decimal digit, it
55
                                    // could never be part of
56
                                    // the escape sequence, which is
57
                                    // confusing
58
                                    if (escapeSequence.length() > 3) {
1 ✔
59
                                        char fourth = escapeSequence.charAt(3);
1 ✔
60
                                        if (isDecimal(fourth)) {
1 !
61
                                            ctx.addViolation(node, "\\" + first + second + third + " + " + fourth);
1 ✔
62
                                        }
63
                                    }
1 ✔
64
                                }
65

66
                            } else if (isDecimal(third)) {
1 !
67
                                // this is a two-digit octal escape followed
68
                                // by a decimal digit
69
                                // legal but very confusing
70
                                ctx.addViolation(node, "\\" + first + second + " + " + third);
1 ✔
71
                            }
72
                        }
1 ✔
73
                    } else if (isDecimal(second)) {
×
74
                        // this is a one-digit octal escape followed by a
75
                        // decimal digit
76
                        // legal but very confusing
NEW
77
                        ctx.addViolation(node, "\\" + first + " + " + second);
×
78
                    }
79
                }
1 ✔
80
            } else if (first == '\\') {
1 ✔
81
                offset++;
1 ✔
82
            }
83
        }
84

85
        return null;
1 ✔
86
    }
87

88
    private boolean isOctal(char c) {
89
        return c >= '0' && c <= '7';
1 ✔
90
    }
91

92
    private boolean isDecimal(char c) {
93
        return c >= '0' && c <= '9';
1 !
94
    }
95
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc