Skip to content

Commit 0b384e3

Browse files
cushongoogle-java-format Team
authored and
google-java-format Team
committed
Prepare g-j-f for some internal javac API changes
* Refactor comment handling in tokenization to avoid extending javac's internal Comment. This prepares for upcoming JDK changes to the Comment API, which break the current subclass approach by changing the return type of `Comment#getPos`, see also similar changes to Error Prone in unknown commit * `JCCompilationUnit#getImports` no longer returns `JCImport`, as part of the changes for modular imports. Supporting modular imports is future work, this change just avoids a crash formatting the existing syntax on the latest JDK versions. PiperOrigin-RevId: 638669955
1 parent b9b6730 commit 0b384e3

File tree

2 files changed

+36
-49
lines changed

2 files changed

+36
-49
lines changed

core/src/main/java/com/google/googlejavaformat/java/JavacTokens.java

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@
1515
package com.google.googlejavaformat.java;
1616

1717
import static com.google.common.base.Preconditions.checkArgument;
18+
import static com.google.common.collect.ImmutableList.toImmutableList;
1819

1920
import com.google.common.collect.ImmutableList;
20-
import com.google.common.collect.Lists;
2121
import com.sun.tools.javac.parser.JavaTokenizer;
2222
import com.sun.tools.javac.parser.Scanner;
2323
import com.sun.tools.javac.parser.ScannerFactory;
2424
import com.sun.tools.javac.parser.Tokens.Comment;
2525
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
2626
import com.sun.tools.javac.parser.Tokens.Token;
2727
import com.sun.tools.javac.parser.Tokens.TokenKind;
28-
import com.sun.tools.javac.parser.UnicodeReader;
2928
import com.sun.tools.javac.util.Context;
29+
import java.util.HashMap;
30+
import java.util.Map;
3031
import java.util.Set;
3132

3233
/** A wrapper around javac's lexer. */
@@ -79,16 +80,16 @@ public static ImmutableList<RawTok> getTokens(
7980
}
8081
ScannerFactory fac = ScannerFactory.instance(context);
8182
char[] buffer = (source + EOF_COMMENT).toCharArray();
82-
Scanner scanner =
83-
new AccessibleScanner(fac, new CommentSavingTokenizer(fac, buffer, buffer.length));
83+
CommentSavingTokenizer tokenizer = new CommentSavingTokenizer(fac, buffer, buffer.length);
84+
Scanner scanner = new AccessibleScanner(fac, tokenizer);
8485
ImmutableList.Builder<RawTok> tokens = ImmutableList.builder();
8586
int end = source.length();
8687
int last = 0;
8788
do {
8889
scanner.nextToken();
8990
Token t = scanner.token();
9091
if (t.comments != null) {
91-
for (Comment c : Lists.reverse(t.comments)) {
92+
for (CommentWithTextAndPosition c : getComments(t, tokenizer.comments())) {
9293
if (last < c.getSourcePos(0)) {
9394
tokens.add(new RawTok(null, null, last, c.getSourcePos(0)));
9495
}
@@ -120,17 +121,36 @@ public static ImmutableList<RawTok> getTokens(
120121
return tokens.build();
121122
}
122123

124+
private static ImmutableList<CommentWithTextAndPosition> getComments(
125+
Token token, Map<Comment, CommentWithTextAndPosition> comments) {
126+
if (token.comments == null) {
127+
return ImmutableList.of();
128+
}
129+
// javac stores the comments in reverse declaration order
130+
return token.comments.stream().map(comments::get).collect(toImmutableList()).reverse();
131+
}
132+
123133
/** A {@link JavaTokenizer} that saves comments. */
124134
static class CommentSavingTokenizer extends JavaTokenizer {
135+
136+
private final Map<Comment, CommentWithTextAndPosition> comments = new HashMap<>();
137+
125138
CommentSavingTokenizer(ScannerFactory fac, char[] buffer, int length) {
126139
super(fac, buffer, length);
127140
}
128141

142+
Map<Comment, CommentWithTextAndPosition> comments() {
143+
return comments;
144+
}
145+
129146
@Override
130147
protected Comment processComment(int pos, int endPos, CommentStyle style) {
131148
char[] buf = getRawCharactersReflectively(pos, endPos);
132-
return new CommentWithTextAndPosition(
133-
pos, endPos, new AccessibleReader(fac, buf, buf.length), style);
149+
Comment comment = super.processComment(pos, endPos, style);
150+
CommentWithTextAndPosition commentWithTextAndPosition =
151+
new CommentWithTextAndPosition(pos, endPos, new String(buf));
152+
comments.put(comment, commentWithTextAndPosition);
153+
return comment;
134154
}
135155

136156
private char[] getRawCharactersReflectively(int beginIndex, int endIndex) {
@@ -153,21 +173,16 @@ private char[] getRawCharactersReflectively(int beginIndex, int endIndex) {
153173
}
154174

155175
/** A {@link Comment} that saves its text and start position. */
156-
static class CommentWithTextAndPosition implements Comment {
176+
static class CommentWithTextAndPosition {
157177

158178
private final int pos;
159179
private final int endPos;
160-
private final AccessibleReader reader;
161-
private final CommentStyle style;
162-
163-
private String text = null;
180+
private final String text;
164181

165-
public CommentWithTextAndPosition(
166-
int pos, int endPos, AccessibleReader reader, CommentStyle style) {
182+
public CommentWithTextAndPosition(int pos, int endPos, String text) {
167183
this.pos = pos;
168184
this.endPos = endPos;
169-
this.reader = reader;
170-
this.style = style;
185+
this.text = text;
171186
}
172187

173188
/**
@@ -176,7 +191,6 @@ public CommentWithTextAndPosition(
176191
* <p>The handling of javadoc comments in javac has more logic to skip over leading whitespace
177192
* and '*' characters when indexing into doc comments, but we don't need any of that.
178193
*/
179-
@Override
180194
public int getSourcePos(int index) {
181195
checkArgument(
182196
0 <= index && index < (endPos - pos),
@@ -186,49 +200,22 @@ public int getSourcePos(int index) {
186200
return pos + index;
187201
}
188202

189-
@Override
190-
public CommentStyle getStyle() {
191-
return style;
192-
}
193-
194-
@Override
195203
public String getText() {
196-
String text = this.text;
197-
if (text == null) {
198-
this.text = text = new String(reader.getRawCharacters());
199-
}
200204
return text;
201205
}
202206

203-
/**
204-
* We don't care about {@code @deprecated} javadoc tags (see the DepAnn check).
205-
*
206-
* @return false
207-
*/
208-
@Override
209-
public boolean isDeprecated() {
210-
return false;
211-
}
212-
213207
@Override
214208
public String toString() {
215209
return String.format("Comment: '%s'", getText());
216210
}
217211
}
218212

219-
// Scanner(ScannerFactory, JavaTokenizer) is package-private
213+
// Scanner(ScannerFactory, JavaTokenizer) is protected
220214
static class AccessibleScanner extends Scanner {
221215
protected AccessibleScanner(ScannerFactory fac, JavaTokenizer tokenizer) {
222216
super(fac, tokenizer);
223217
}
224218
}
225219

226-
// UnicodeReader(ScannerFactory, char[], int) is package-private
227-
static class AccessibleReader extends UnicodeReader {
228-
protected AccessibleReader(ScannerFactory fac, char[] buffer, int length) {
229-
super(fac, buffer, length);
230-
}
231-
}
232-
233220
private JavacTokens() {}
234221
}

core/src/main/java/com/google/googlejavaformat/java/RemoveUnusedImports.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ private static RangeMap<Integer, String> buildReplacements(
273273
Set<String> usedNames,
274274
Multimap<String, Range<Integer>> usedInJavadoc) {
275275
RangeMap<Integer, String> replacements = TreeRangeMap.create();
276-
for (JCImport importTree : unit.getImports()) {
276+
for (JCTree importTree : unit.getImports()) {
277277
String simpleName = getSimpleName(importTree);
278278
if (!isUnused(unit, usedNames, usedInJavadoc, importTree, simpleName)) {
279279
continue;
@@ -291,15 +291,15 @@ private static RangeMap<Integer, String> buildReplacements(
291291
return replacements;
292292
}
293293

294-
private static String getSimpleName(JCImport importTree) {
294+
private static String getSimpleName(JCTree importTree) {
295295
return getQualifiedIdentifier(importTree).getIdentifier().toString();
296296
}
297297

298298
private static boolean isUnused(
299299
JCCompilationUnit unit,
300300
Set<String> usedNames,
301301
Multimap<String, Range<Integer>> usedInJavadoc,
302-
JCImport importTree,
302+
JCTree importTree,
303303
String simpleName) {
304304
JCFieldAccess qualifiedIdentifier = getQualifiedIdentifier(importTree);
305305
String qualifier = qualifiedIdentifier.getExpression().toString();
@@ -322,7 +322,7 @@ private static boolean isUnused(
322322
return true;
323323
}
324324

325-
private static JCFieldAccess getQualifiedIdentifier(JCImport importTree) {
325+
private static JCFieldAccess getQualifiedIdentifier(JCTree importTree) {
326326
// Use reflection because the return type is JCTree in some versions and JCFieldAccess in others
327327
try {
328328
return (JCFieldAccess) JCImport.class.getMethod("getQualifiedIdentifier").invoke(importTree);

0 commit comments

Comments
 (0)