Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling of SYNTHETIC and BRIDGE modifiers added #243

Merged
merged 2 commits into from
Oct 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ public enum JavaModifier {
@PublicAPI(usage = ACCESS)
SYNCHRONIZED(EnumSet.of(ApplicableType.METHOD), Opcodes.ACC_SYNCHRONIZED),
@PublicAPI(usage = ACCESS)
NATIVE(EnumSet.of(ApplicableType.METHOD), Opcodes.ACC_NATIVE);
NATIVE(EnumSet.of(ApplicableType.METHOD), Opcodes.ACC_NATIVE),
@PublicAPI(usage = ACCESS)
BRIDGE(EnumSet.of(ApplicableType.METHOD), Opcodes.ACC_BRIDGE),
@PublicAPI(usage = ACCESS)
SYNTHETIC(EnumSet.allOf(ApplicableType.class), Opcodes.ACC_SYNTHETIC);

private final Set<ApplicableType> applicableTo;
private final int asmAccessFlag;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
import com.tngtech.archunit.core.importer.testexamples.simpleimport.InterfaceToImport;
import com.tngtech.archunit.core.importer.testexamples.simplenames.SimpleNameExamples;
import com.tngtech.archunit.core.importer.testexamples.specialtargets.ClassCallingSpecialTarget;
import com.tngtech.archunit.core.importer.testexamples.syntheticimport.ClassWithSynthetics;
import com.tngtech.archunit.testutil.LogTestRule;
import com.tngtech.archunit.testutil.OutsideOfClassPathRule;
import com.tngtech.java.junit.dataprovider.DataProvider;
Expand All @@ -194,11 +195,13 @@
import static com.tngtech.archunit.core.domain.JavaConstructor.CONSTRUCTOR_NAME;
import static com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType.GET;
import static com.tngtech.archunit.core.domain.JavaFieldAccess.AccessType.SET;
import static com.tngtech.archunit.core.domain.JavaModifier.BRIDGE;
import static com.tngtech.archunit.core.domain.JavaModifier.FINAL;
import static com.tngtech.archunit.core.domain.JavaModifier.PRIVATE;
import static com.tngtech.archunit.core.domain.JavaModifier.PROTECTED;
import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC;
import static com.tngtech.archunit.core.domain.JavaModifier.STATIC;
import static com.tngtech.archunit.core.domain.JavaModifier.SYNTHETIC;
import static com.tngtech.archunit.core.domain.JavaModifier.TRANSIENT;
import static com.tngtech.archunit.core.domain.JavaModifier.VOLATILE;
import static com.tngtech.archunit.core.domain.JavaStaticInitializer.STATIC_INITIALIZER_NAME;
Expand Down Expand Up @@ -384,6 +387,20 @@ public void handles_static_modifier_of_nested_classes() throws Exception {
assertThat(classes.get(ClassWithNestedClass.StaticNestedInterface.class).getModifiers()).as("modifiers of ClassWithNestedClass.StaticNestedInterface").contains(STATIC);
}

@Test
public void handles_synthetic_modifiers() throws Exception {
JavaClasses classes = classesIn("testexamples/syntheticimport").classes;

JavaField syntheticField = getOnlyElement(classes.get(ClassWithSynthetics.ClassWithSyntheticField.class).getFields());
assertThat(syntheticField.getModifiers()).as("modifiers of field in ClassWithSynthetics.ClassWithSyntheticField").contains(SYNTHETIC);

JavaMethod syntheticMethod = getOnlyElement(classes.get(ClassWithSynthetics.ClassWithSyntheticMethod.class).getMethods());
assertThat(syntheticMethod.getModifiers()).as("modifiers of method in ClassWithSynthetics.ClassWithSyntheticMethod").contains(SYNTHETIC);

JavaMethod compareMethod = classes.get(ClassWithSynthetics.class).getMethod("compare", Object.class, Object.class);
assertThat(compareMethod.getModifiers()).as("modifiers of bridge method in ClassWithSynthetics").contains(BRIDGE, SYNTHETIC);
}

@Test
public void imports_jdk_classes() {
JavaClasses classes = new ClassFileImporter().importClasses(File.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.tngtech.archunit.core.importer.testexamples.syntheticimport;

import java.util.Comparator;

@SuppressWarnings({"unused", "InnerClassMayBeStatic"})
public class ClassWithSynthetics implements Comparator<String> {
// for (non-static) inner classes the compiler must create a synthetic field, holding a reference to the outer class
public class ClassWithSyntheticField {
}

// for accesses to private fields of inner classes, the compiler must create a synthetic method to allow access to this field
// thus together with the method 'getNestedField', this causes the existence of a synthetic method
public class ClassWithSyntheticMethod {
private String nestedField;
}

public String getNestedField() {
return new ClassWithSyntheticMethod().nestedField;
}

// to cover type erasure, the compiler must add a bridge method with signature compare(Object, Object) here
@Override
public int compare(String o1, String o2) {
return 0;
}
}