@@ -296,70 +296,104 @@ private static class ImportsAndIndex {
296
296
private ImportsAndIndex scanImports (int i ) throws FormatterException {
297
297
int afterLastImport = i ;
298
298
ImmutableSortedSet .Builder <Import > imports = ImmutableSortedSet .orderedBy (importComparator );
299
- // JavaInput.buildToks appends a zero-width EOF token after all tokens. It won't match any
300
- // of our tests here and protects us from running off the end of the toks list. Since it is
301
- // zero-width it doesn't matter if we include it in our string concatenation at the end.
299
+
302
300
while (i < toks .size () && tokenAt (i ).equals ("import" )) {
303
- i ++;
304
- if (isSpaceToken (i )) {
305
- i ++;
306
- }
307
- boolean isStatic = tokenAt (i ).equals ("static" );
308
- if (isStatic ) {
309
- i ++;
310
- if (isSpaceToken (i )) {
311
- i ++;
312
- }
313
- }
314
- if (!isIdentifierToken (i )) {
315
- throw new FormatterException ("Unexpected token after import: " + tokenAt (i ));
316
- }
317
- StringAndIndex imported = scanImported (i );
318
- String importedName = imported .string ;
319
- i = imported .index ;
320
- if (isSpaceToken (i )) {
321
- i ++;
322
- }
323
- if (!tokenAt (i ).equals (";" )) {
324
- throw new FormatterException ("Expected ; after import" );
325
- }
326
- while (tokenAt (i ).equals (";" )) {
327
- // Extra semicolons are not allowed by the JLS but are accepted by javac.
301
+ ImportAndIndex result = scanSingleImport (i );
302
+ imports .add (result .importStatement );
303
+ i = result .index ;
304
+ afterLastImport = i ;
305
+
306
+ // Skip any whitespace but preserve comment positions
307
+ while (isNewlineToken (i ) || isSpaceToken (i )) {
328
308
i ++;
329
309
}
330
- StringBuilder trailing = new StringBuilder ();
310
+ }
311
+
312
+ return new ImportsAndIndex (imports .build (), afterLastImport );
313
+ }
314
+
315
+ private static class ImportAndIndex {
316
+ final Import importStatement ;
317
+ final int index ;
318
+
319
+ ImportAndIndex (Import importStatement , int index ) {
320
+ this .importStatement = importStatement ;
321
+ this .index = index ;
322
+ }
323
+ }
324
+
325
+ private ImportAndIndex scanSingleImport (int i ) throws FormatterException {
326
+ // Skip 'import' and following space
327
+ i ++;
328
+ if (isSpaceToken (i )) {
329
+ i ++;
330
+ }
331
+
332
+ // Handle static keyword
333
+ boolean isStatic = tokenAt (i ).equals ("static" );
334
+ if (isStatic ) {
335
+ i ++;
331
336
if (isSpaceToken (i )) {
332
- trailing .append (tokenAt (i ));
333
337
i ++;
334
338
}
339
+ }
340
+
341
+ if (!isIdentifierToken (i )) {
342
+ throw new FormatterException ("Unexpected token after import: " + tokenAt (i ));
343
+ }
344
+
345
+ StringAndIndex imported = scanImported (i );
346
+ String importedName = imported .string ;
347
+ i = imported .index ;
348
+
349
+ // Handle semicolon and spaces
350
+ if (isSpaceToken (i )) {
351
+ i ++;
352
+ }
353
+ if (!tokenAt (i ).equals (";" )) {
354
+ throw new FormatterException ("Expected ; after import" );
355
+ }
356
+
357
+ // Collect all trailing content (including comments)
358
+ StringBuilder trailing = new StringBuilder ();
359
+ i = collectTrailingContent (i , trailing );
360
+
361
+ Import importStatement = new Import (importedName , trailing .toString (), isStatic );
362
+ return new ImportAndIndex (importStatement , i );
363
+ }
364
+
365
+ private int collectTrailingContent (int i , StringBuilder trailing ) {
366
+ // Collect all semicolons
367
+ while (tokenAt (i ).equals (";" )) {
368
+ i ++;
369
+ }
370
+
371
+ // Collect whitespace and newline
372
+ if (isSpaceToken (i )) {
373
+ trailing .append (tokenAt (i ));
374
+ i ++;
375
+ }
376
+ if (isNewlineToken (i )) {
377
+ trailing .append (tokenAt (i ));
378
+ i ++;
379
+ }
380
+
381
+ // Collect comments and their newlines
382
+ while (isSlashSlashCommentToken (i )) {
383
+ trailing .append (tokenAt (i ));
384
+ i ++;
335
385
if (isNewlineToken (i )) {
336
386
trailing .append (tokenAt (i ));
337
387
i ++;
338
388
}
339
- // Gather (if any) all single line comments and accompanied line terminators following this
340
- // import
341
- while (isSlashSlashCommentToken (i )) {
342
- trailing .append (tokenAt (i ));
343
- i ++;
344
- if (isNewlineToken (i )) {
345
- trailing .append (tokenAt (i ));
346
- i ++;
347
- }
348
- }
349
- while (tokenAt (i ).equals (";" )) {
350
- // Extra semicolons are not allowed by the JLS but are accepted by javac.
351
- i ++;
352
- }
353
- imports .add (new Import (importedName , trailing .toString (), isStatic ));
354
- // Remember the position just after the import we just saw, before skipping blank lines.
355
- // If the next thing after the blank lines is not another import then we don't want to
356
- // include those blank lines in the text to be replaced.
357
- afterLastImport = i ;
358
- while (isNewlineToken (i ) || isSpaceToken (i )) {
359
- i ++;
360
- }
361
389
}
362
- return new ImportsAndIndex (imports .build (), afterLastImport );
390
+
391
+ // Collect any remaining semicolons
392
+ while (tokenAt (i ).equals (";" )) {
393
+ i ++;
394
+ }
395
+
396
+ return i ;
363
397
}
364
398
365
399
// Produces the sorted output based on the imports we have scanned.
0 commit comments