1
2
3
4
5 package com.qulice.checkstyle;
6
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.regex.Matcher;
14 import java.util.regex.Pattern;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 final class Suppressions implements Iterable<SuppressionTag> {
38
39
40
41
42 private static final Pattern NEARBY = Pattern.compile(
43 "@checkstyle (\\w+) \\((\\d+) lines?\\)"
44 );
45
46
47
48
49 private static final Pattern DISABLE = Pattern.compile(
50 "@checkstyle (\\w+) disable"
51 );
52
53
54
55
56 private static final Pattern ENABLE = Pattern.compile(
57 "@checkstyle (\\w+) enable"
58 );
59
60
61
62
63 private final String text;
64
65
66
67
68
69
70 Suppressions(final String text) {
71 this.text = text;
72 }
73
74 @Override
75 public Iterator<SuppressionTag> iterator() {
76 final List<String> lines = new ArrayList<>(0);
77 this.text.lines().forEach(lines::add);
78 final Collection<SuppressionTag> tags = new ArrayList<>(0);
79 final Map<String, Integer> open = new HashMap<>(0);
80 for (int idx = 0; idx < lines.size(); ++idx) {
81 final int number = idx + 1;
82 final String line = Suppressions.code(lines.get(idx));
83 Suppressions.nearby(line, number, tags);
84 final Matcher disable = Suppressions.DISABLE.matcher(line);
85 while (disable.find()) {
86 open.putIfAbsent(disable.group(1), number);
87 }
88 final Matcher enable = Suppressions.ENABLE.matcher(line);
89 while (enable.find()) {
90 final Integer start = open.remove(enable.group(1));
91 if (start != null) {
92 tags.add(new SuppressionTag(enable.group(1), start, number));
93 }
94 }
95 }
96 for (final Map.Entry<String, Integer> entry : open.entrySet()) {
97 tags.add(
98 new SuppressionTag(entry.getKey(), entry.getValue(), lines.size())
99 );
100 }
101 return tags.iterator();
102 }
103
104 private static void nearby(final String line, final int number,
105 final Collection<SuppressionTag> tags) {
106 final Matcher matcher = Suppressions.NEARBY.matcher(line);
107 while (matcher.find()) {
108 tags.add(
109 new SuppressionTag(
110 matcher.group(1),
111 number,
112 number + Integer.parseInt(matcher.group(2))
113 )
114 );
115 }
116 }
117
118 private static String code(final String line) {
119 final StringBuilder out = new StringBuilder(line.length());
120 char quote = 0;
121 boolean escape = false;
122 for (int idx = 0; idx < line.length(); ++idx) {
123 final char chr = line.charAt(idx);
124 if (quote == 0 && (chr == '"' || chr == '\'')) {
125 quote = chr;
126 out.append(chr);
127 } else if (quote == 0) {
128 out.append(chr);
129 } else if (escape) {
130 escape = false;
131 out.append(' ');
132 } else if (chr == '\\') {
133 escape = true;
134 out.append(' ');
135 } else if (chr == quote) {
136 quote = 0;
137 out.append(chr);
138 } else {
139 out.append(' ');
140 }
141 }
142 return out.toString();
143 }
144 }