@@ -360,6 +360,32 @@ private IType[] resolveMissingTypes(IProgressMonitor monitor) throws JavaModelEx
360
360
}
361
361
}
362
362
363
+ /**
364
+ * Determines if organize imports is unsafe due to syntax errors or other conditions.
365
+ */
366
+ private static boolean isUnclean (ModuleNodeInfo info , GroovyCompilationUnit unit ) {
367
+ try {
368
+ if (info .module .encounteredUnrecoverableError () || !unit .isConsistent ()) {
369
+ return true ;
370
+ }
371
+ CategorizedProblem [] problems = info .result .getProblems ();
372
+ if (problems != null && problems .length > 0 ) {
373
+ for (CategorizedProblem problem : problems ) {
374
+ if (problem .isError () && problem .getCategoryID () == CategorizedProblem .CAT_INTERNAL ) {
375
+ String message = problem .getMessage ();
376
+ if (message .contains ("unexpected token" )) {
377
+ trace ("Stopping due to error in compilation unit: %s" , message );
378
+ return true ;
379
+ }
380
+ }
381
+ }
382
+ }
383
+ } catch (Exception e ) {
384
+ return true ;
385
+ }
386
+ return false ;
387
+ }
388
+
363
389
/**
364
390
* GRECLIPSE-1390
365
391
* Reorganizing imports (ie- sorting and grouping them) will remove annotations on import statements
@@ -376,16 +402,16 @@ private static boolean isSafeToReorganize(Iterable<ImportNode> allImports) {
376
402
return true ;
377
403
}
378
404
379
- private static boolean isAliased (ImportNode imp ) {
380
- String alias = imp .getAlias ();
405
+ private static boolean isAliased (ImportNode node ) {
406
+ String alias = node .getAlias ();
381
407
if (alias == null ) {
382
408
return false ;
383
409
}
384
- String fieldName = imp .getFieldName ();
410
+ String fieldName = node .getFieldName ();
385
411
if (fieldName != null ) {
386
412
return !fieldName .equals (alias );
387
413
}
388
- String className = imp .getClassName ();
414
+ String className = node .getClassName ();
389
415
if (className != null ) {
390
416
// it is possible to import from the default package
391
417
boolean aliasIsSameAsClassName = className .endsWith (alias ) &&
@@ -395,30 +421,14 @@ private static boolean isAliased(ImportNode imp) {
395
421
return false ;
396
422
}
397
423
398
- /**
399
- * Determines if organize imports is unsafe due to syntax errors or other conditions.
400
- */
401
- private static boolean isUnclean (ModuleNodeInfo info , GroovyCompilationUnit unit ) {
402
- try {
403
- if (info .module .encounteredUnrecoverableError () || !unit .isConsistent ()) {
404
- return true ;
405
- }
406
- CategorizedProblem [] problems = info .result .getProblems ();
407
- if (problems != null && problems .length > 0 ) {
408
- for (CategorizedProblem problem : problems ) {
409
- if (problem .isError () && problem .getCategoryID () == CategorizedProblem .CAT_INTERNAL ) {
410
- String message = problem .getMessage ();
411
- if (message .contains ("unexpected token" )) {
412
- trace ("Stopping due to error in compilation unit: %s" , message );
413
- return true ;
414
- }
415
- }
416
- }
417
- }
418
- } catch (Exception e ) {
419
- return true ;
424
+ private static String getTypeName (ClassNode node ) {
425
+ ClassNode type = GroovyUtils .getBaseType (node );
426
+ // unresolved name may have dots and/or dollars (e.g. 'a.b.C$D' or 'C$D' or even 'C.D')
427
+ if (!type .getName ().matches (".*\\ b" + type .getUnresolvedName ().replace ('$' , '.' ))) {
428
+ // synch up name and unresolved name (e.g. 'java.util.Map$Entry as Foo$Entry')
429
+ return type .getName () + " as " + type .getUnresolvedName ().replace ('.' , '$' );
420
430
}
421
- return false ;
431
+ return type . getName () ;
422
432
}
423
433
424
434
private static void trace (String message , Object ... arguments ) {
@@ -691,10 +701,9 @@ private void handleTypeReference(ClassNode node, boolean isAnnotation) {
691
701
name = name .replaceAll (Pattern .quote (name .substring (i )) + "(?= |$)" , "" );
692
702
}
693
703
doNotRemoveImport (name .replace ('$' , '.' ));
694
- return ;
695
- }
696
-
697
- if (!node .isResolved () && !current .getModule ().getClasses ().contains (node .redirect ())) {
704
+ } else if (current .getModule ().getClasses ().contains (node )) {
705
+ // keep in importsSlatedForRemoval and leave out of missingTypes
706
+ } else if (!node .isResolved ()) {
698
707
String [] parts = name .split ("\\ ." );
699
708
if (Character .isUpperCase (name .charAt (0 ))) {
700
709
name = parts [0 ]; // 'Map.Entry' -> 'Map'
@@ -714,15 +723,17 @@ private void handleTypeReference(ClassNode node, boolean isAnnotation) {
714
723
while (i < chars .length && Character .isJavaIdentifierPart (chars [i ])) {
715
724
i += 1 ;
716
725
}
726
+ // for a 'Map.Entry' reference find '.Map' in 'java.util.Map' or '.Map$' in 'java.util.Map$Entry'
717
727
m = Pattern .compile ("(?:\\ A|\\ $|\\ .)" + String .valueOf (chars , 0 , i ) + "(?=\\ $|$)" ).matcher (name );
718
728
if (m .find ()) {
719
729
// 'java.util.Map$Entry' -> 'java.util.Map'
720
- String partialName = name .substring (0 , m .end ()).replace ('$' , '.' );
721
- doNotRemoveImport (partialName );
730
+ String partialName = name .substring (0 , m .end ());
731
+ if (!isInnerOfSuper (partialName ))
732
+ doNotRemoveImport (partialName .replace ('$' , '.' ));
722
733
}
723
734
} else {
724
- // We don't know exactly what the text is. We just know how
725
- // it resolves. This can be a problem if an inner class. We
735
+ // We do not know exactly what the text is. We just know how
736
+ // it resolves. This can be a problem for an inner class. We
726
737
// don't really know what is in the text nor what the import
727
738
// is, so just ensure that none are slated for removal.
728
739
String partialName = name .replace ('$' , '.' );
@@ -740,14 +751,31 @@ private void handleTypeReference(ClassNode node, boolean isAnnotation) {
740
751
}
741
752
}
742
753
743
- private String getTypeName (ClassNode node ) {
744
- ClassNode type = GroovyUtils .getBaseType (node );
745
- // unresolved name may have dots and/or dollars (e.g. 'a.b.C$D' or 'C$D' or even 'C.D')
746
- if (!type .getName ().matches (".*\\ b" + type .getUnresolvedName ().replace ('$' , '.' ))) {
747
- // synch up name and unresolved name (e.g. 'java.util.Map$Entry as Foo$Entry')
748
- return type .getName () + " as " + type .getUnresolvedName ().replace ('.' , '$' );
754
+ private boolean isInnerOfSuper (String name ) {
755
+ if (name .lastIndexOf ('$' ) > 0 ) {
756
+ for (ClassNode node = current .getSuperClass (); node != null && !node .equals (ClassHelper .OBJECT_TYPE ); node = node .getSuperClass ()) {
757
+ for (Iterator <? extends ClassNode > it = node .redirect ().getInnerClasses (); it .hasNext ();) {
758
+ if (it .next ().getName ().equals (name )) {
759
+ return true ;
760
+ }
761
+ }
762
+ }
763
+
764
+ java .util .Queue <ClassNode > todo = new java .util .ArrayDeque <>();
765
+ java .util .Collections .addAll (todo , current .getInterfaces ());
766
+ Set <ClassNode > done = new LinkedHashSet <>();
767
+ ClassNode node ;
768
+
769
+ while ((node = todo .poll ()) != null ) { if (!done .add (node )) continue ;
770
+ for (Iterator <? extends ClassNode > it = node .redirect ().getInnerClasses (); it .hasNext ();) {
771
+ if (it .next ().getName ().equals (name )) {
772
+ return true ;
773
+ }
774
+ }
775
+ java .util .Collections .addAll (todo , node .getInterfaces ());
776
+ }
749
777
}
750
- return type . getName () ;
778
+ return false ;
751
779
}
752
780
753
781
private boolean checkRetainImport (String name ) {
0 commit comments