Hiding default constructor with respect to its access modifiers

master
upnotes 6 years ago committed by Roman Shevchenko
parent 02fdbec132
commit 2431c0fe94
  1. 20
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  2. 1
      test/org/jetbrains/java/decompiler/SingleClassesTest.java
  3. BIN
      testData/classes/pkg/TestPrivateEmptyConstructor.class
  4. 26
      testData/results/TestPrivateEmptyConstructor.dec
  5. 10
      testData/src/pkg/TestPrivateEmptyConstructor.java

@ -820,7 +820,7 @@ public class ClassWriter {
BytecodeMappingTracer codeTracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine());
TextBuffer code = root.toJava(indent + 1, codeTracer);
hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
hideMethod = (code.length() == 0) && (clinit || dinit || hideConstructor(node, init, throwsExceptions, paramCount, flags));
buffer.append(code);
@ -859,13 +859,25 @@ public class ClassWriter {
return !hideMethod;
}
private static boolean hideConstructor(ClassWrapper wrapper, boolean init, boolean throwsExceptions, int paramCount) {
private static boolean hideConstructor(ClassNode node, boolean init, boolean throwsExceptions, int paramCount, int methodAccessFlags) {
if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) {
return false;
}
ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
int classAccesFlags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access;
boolean isEnum = cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
// default constructor requires same accessibility flags. Exception: enum constructor which is always private
if(!isEnum && ((classAccesFlags & ACCESSIBILITY_FLAGS) != (methodAccessFlags & ACCESSIBILITY_FLAGS))) {
return false;
}
int count = 0;
for (StructMethod mt : wrapper.getClassStruct().getMethods()) {
for (StructMethod mt : cl.getMethods()) {
if (CodeConstants.INIT_NAME.equals(mt.getName())) {
if (++count > 1) {
return false;
@ -1031,6 +1043,8 @@ public class ClassWriter {
private static final int FIELD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL;
private static final int METHOD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_ABSTRACT;
private static final int ACCESSIBILITY_FLAGS = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE;
private static void appendModifiers(TextBuffer buffer, int flags, int allowed, boolean isInterface, int excluded) {
flags &= allowed;
if (!isInterface) excluded = 0;

@ -108,6 +108,7 @@ public class SingleClassesTest {
@Test public void testMissingConstructorCallGood() { doTest("pkg/TestMissingConstructorCallGood"); }
@Test public void testMissingConstructorCallBad() { doTest("pkg/TestMissingConstructorCallBad"); }
@Test public void testEmptyBlocks() { doTest("pkg/TestEmptyBlocks"); }
@Test public void testPrivateEmptyConstructor() { doTest("pkg/TestPrivateEmptyConstructor"); }
// TODO: fix all below

@ -0,0 +1,26 @@
public final class TestPrivateEmptyConstructor {
private TestPrivateEmptyConstructor() {
}// 4
public final void test() {
System.out.println("test");// 7
}// 8
}
class 'TestPrivateEmptyConstructor' {
method '<init> ()V' {
4 2
}
method 'test ()V' {
0 5
3 5
5 5
8 6
}
}
Lines mapping:
4 <-> 3
7 <-> 6
8 <-> 7

@ -0,0 +1,10 @@
public final class PrivateEmptyConstructor {
private PrivateEmptyConstructor() {}
public final void test() {
System.out.println("test");
}
}
Loading…
Cancel
Save