Fix short name imports shadowed by super inner classes
This commit is contained in:
@@ -5,6 +5,7 @@ package org.jetbrains.java.decompiler.main.collectors;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.struct.attr.StructInnerClassesAttribute;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||
import org.jetbrains.java.decompiler.struct.StructContext;
|
||||
@@ -20,6 +21,7 @@ public class ImportCollector {
|
||||
private final Set<String> setNotImportedNames = new HashSet<>();
|
||||
// set of field names in this class and all its predecessors.
|
||||
private final Set<String> setFieldNames = new HashSet<>();
|
||||
private final Set<String> setInnerClassNames = new HashSet<>();
|
||||
private final String currentPackageSlash;
|
||||
private final String currentPackagePoint;
|
||||
|
||||
@@ -37,15 +39,37 @@ public class ImportCollector {
|
||||
}
|
||||
|
||||
Map<String, StructClass> classes = DecompilerContext.getStructContext().getClasses();
|
||||
LinkedList<String> queue = new LinkedList<>();
|
||||
StructClass currentClass = root.classStruct;
|
||||
while (currentClass != null) {
|
||||
if (currentClass.superClass != null) {
|
||||
queue.add(currentClass.superClass.getString());
|
||||
}
|
||||
|
||||
Collections.addAll(queue, currentClass.getInterfaceNames());
|
||||
|
||||
// all field names for the current class ..
|
||||
for (StructField f : currentClass.getFields()) {
|
||||
setFieldNames.add(f.getName());
|
||||
}
|
||||
|
||||
// .. all inner classes for the current class ..
|
||||
if (currentClass.hasAttribute(StructInnerClassesAttribute.ATTRIBUTE_INNER_CLASSES)) {
|
||||
StructInnerClassesAttribute attribute =
|
||||
(StructInnerClassesAttribute)currentClass.getAttribute(StructInnerClassesAttribute.ATTRIBUTE_INNER_CLASSES);
|
||||
|
||||
for (StructInnerClassesAttribute.Entry entry : attribute.getEntries()) {
|
||||
if (entry.enclosingName != null && entry.enclosingName.equals(currentClass.qualifiedName)) {
|
||||
setInnerClassNames.add(entry.simpleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .. and traverse through parent.
|
||||
currentClass = currentClass.superClass != null ? classes.get(currentClass.superClass.getString()) : null;
|
||||
currentClass = !queue.isEmpty() ? classes.get(queue.removeFirst()) : null;
|
||||
while (currentClass == null && !queue.isEmpty()) {
|
||||
currentClass = classes.get(queue.removeFirst());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,12 +129,14 @@ public class ImportCollector {
|
||||
|
||||
StructContext context = DecompilerContext.getStructContext();
|
||||
|
||||
// check for another class which could 'shadow' this one. Two cases:
|
||||
// check for another class which could 'shadow' this one. Three cases:
|
||||
// 1) class with the same short name in the current package
|
||||
// 2) class with the same short name in the default package
|
||||
// 3) inner class with the same short name in the current class, a super class, or an implemented interface
|
||||
boolean existsDefaultClass =
|
||||
(context.getClass(currentPackageSlash + shortName) != null && !packageName.equals(currentPackagePoint)) || // current package
|
||||
(context.getClass(shortName) != null && !currentPackagePoint.isEmpty()); // default package
|
||||
(context.getClass(shortName) != null && !currentPackagePoint.isEmpty()) || // default package
|
||||
setInnerClassNames.contains(shortName); // inner class
|
||||
|
||||
if (existsDefaultClass ||
|
||||
(mapSimpleNames.containsKey(shortName) && !packageName.equals(mapSimpleNames.get(shortName)))) {
|
||||
|
||||
@@ -70,7 +70,8 @@ public class SingleClassesTest {
|
||||
@Test public void testAnonymousSignature() { doTest("pkg/TestAnonymousSignature"); }
|
||||
@Test public void testLocalsSignature() { doTest("pkg/TestLocalsSignature"); }
|
||||
@Test public void testParameterizedTypes() { doTest("pkg/TestParameterizedTypes"); }
|
||||
@Test public void testShadowing() { doTest("pkg/TestShadowing", "pkg/Shadow", "ext/Shadow"); }
|
||||
@Test public void testShadowing() { doTest("pkg/TestShadowing", "pkg/Shadow", "ext/Shadow",
|
||||
"pkg/TestShadowingSuperClass"); }
|
||||
@Test public void testStringConcat() { doTest("pkg/TestStringConcat"); }
|
||||
@Test public void testJava9StringConcat() { doTest("java9/TestJava9StringConcat"); }
|
||||
@Test public void testMethodReferenceSameName() { doTest("pkg/TestMethodReferenceSameName"); }
|
||||
|
||||
Binary file not shown.
BIN
testData/classes/pkg/TestShadowingSuperClass$Builder.class
Normal file
BIN
testData/classes/pkg/TestShadowingSuperClass$Builder.class
Normal file
Binary file not shown.
BIN
testData/classes/pkg/TestShadowingSuperClass.class
Normal file
BIN
testData/classes/pkg/TestShadowingSuperClass.class
Normal file
Binary file not shown.
@@ -1,6 +1,7 @@
|
||||
package pkg;
|
||||
|
||||
class TestShadowing {
|
||||
class TestShadowing extends TestShadowingSuperClass {
|
||||
ext.Shadow.B instanceOfB = new ext.Shadow.B();
|
||||
java.util.Calendar.Builder calBuilder = new java.util.Calendar.Builder();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
package pkg;
|
||||
|
||||
class TestShadowing {
|
||||
import java.util.Calendar;
|
||||
|
||||
class TestShadowing extends TestShadowingSuperClass {
|
||||
ext.Shadow.B instanceOfB = new ext.Shadow.B();
|
||||
Calendar.Builder calBuilder = new Calendar.Builder();
|
||||
}
|
||||
|
||||
class TestShadowingSuperClass {
|
||||
static class Builder { }
|
||||
}
|
||||
Reference in New Issue
Block a user