Refactor ReadKotlinClassHeaderAnnotationVisitor

Extract a hierarchy of four nested classes instead of anonymous
This commit is contained in:
Alexander Udalov
2015-02-14 01:43:02 +03:00
parent 5d8ae3ed6a
commit add9bb34cb
@@ -96,11 +96,11 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
switch (newKind) { switch (newKind) {
case CLASS: case CLASS:
return kotlinClassOrPackageVisitor(annotation); return new ClassHeaderReader();
case PACKAGE_FACADE: case PACKAGE_FACADE:
return kotlinClassOrPackageVisitor(annotation); return new PackageHeaderReader();
case SYNTHETIC_CLASS: case SYNTHETIC_CLASS:
return syntheticClassAnnotationVisitor(); return new SyntheticClassHeaderReader();
default: default:
throw new IllegalStateException("Unknown kind: " + newKind); throw new IllegalStateException("Unknown kind: " + newKind);
} }
@@ -118,111 +118,112 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
public void visitEnd() { public void visitEnd() {
} }
@NotNull private abstract class HeaderAnnotationArgumentVisitor implements AnnotationArgumentVisitor {
private AnnotationArgumentVisitor kotlinClassOrPackageVisitor(@NotNull final JvmClassName annotationClassName) { protected final JvmClassName annotationClassName;
return new AnnotationArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, annotationClassName);
}
@Override public HeaderAnnotationArgumentVisitor(@NotNull JvmClassName annotationClassName) {
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) { this.annotationClassName = annotationClassName;
unexpectedArgument(name, annotationClassName);
}
@Override
@Nullable
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + annotationClassName);
}
return null;
}
@NotNull
private AnnotationArrayArgumentVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1);
return new AnnotationArrayArgumentVisitor() {
@Override
public void visit(@Nullable Object value) {
if (!(value instanceof String)) {
throw new IllegalStateException("Unexpected argument value: " + value);
}
strings.add((String) value);
}
@Override
public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
unexpectedArgument(null, annotationClassName);
}
@Override
public void visitEnd() {
//noinspection SSBasedInspection
annotationData = strings.toArray(new String[strings.size()]);
}
};
}
@Override
public void visitEnd() {
}
};
}
@NotNull
private AnnotationArgumentVisitor syntheticClassAnnotationVisitor() {
return new AnnotationArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
visitIntValueForSupportedAnnotation(name, value, KotlinSyntheticClass.CLASS_NAME);
}
@Override
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
if (enumClassId.equals(KotlinSyntheticClass.KIND_CLASS_ID) && name.asString().equals(KIND_FIELD_NAME)) {
syntheticClassKind = valueOfOrNull(KotlinSyntheticClass.Kind.class, enumEntryName.asString());
if (syntheticClassKind != null) return;
}
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected enum entry for synthetic class annotation: " +
name + "=" + enumClassId + "." + enumEntryName);
}
}
@Nullable
@Override
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
return unexpectedArgument(name, KotlinSyntheticClass.CLASS_NAME);
}
@Override
public void visitEnd() {
}
};
}
private void visitIntValueForSupportedAnnotation(@Nullable Name name, @Nullable Object value, @NotNull JvmClassName className) {
if (name != null && name.asString().equals(ABI_VERSION_FIELD_NAME)) {
version = value == null ? AbiVersionUtil.INVALID_VERSION : (Integer) value;
} }
else {
unexpectedArgument(name, className); @Override
public void visit(@Nullable Name name, @Nullable Object value) {
if (name != null && name.asString().equals(ABI_VERSION_FIELD_NAME)) {
version = value == null ? AbiVersionUtil.INVALID_VERSION : (Integer) value;
}
else {
unexpectedArgument(name);
}
}
@Override
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
unexpectedEnumArgument(name, enumClassId, enumEntryName);
}
@Override
@Nullable
public AnnotationArrayArgumentVisitor visitArray(@NotNull Name name) {
if (name.asString().equals(DATA_FIELD_NAME)) {
return stringArrayVisitor();
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + annotationClassName);
}
return null;
}
@NotNull
private AnnotationArrayArgumentVisitor stringArrayVisitor() {
final List<String> strings = new ArrayList<String>(1);
return new AnnotationArrayArgumentVisitor() {
@Override
public void visit(@Nullable Object value) {
if (!(value instanceof String)) {
throw new IllegalStateException("Unexpected argument value: " + value);
}
strings.add((String) value);
}
@Override
public void visitEnum(@NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
unexpectedArgument(null);
}
@Override
public void visitEnd() {
//noinspection SSBasedInspection
annotationData = strings.toArray(new String[strings.size()]);
}
};
}
@Nullable
protected AnnotationArrayArgumentVisitor unexpectedArgument(@Nullable Name name) {
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + annotationClassName);
}
return null;
}
protected void unexpectedEnumArgument(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected enum entry for class annotation " + annotationClassName + ": " +
name + "=" + enumClassId + "." + enumEntryName);
}
}
@Override
public void visitEnd() {
} }
} }
@Nullable private class ClassHeaderReader extends HeaderAnnotationArgumentVisitor {
private AnnotationArrayArgumentVisitor unexpectedArgument(@Nullable Name name, @NotNull JvmClassName annotationClassName) { public ClassHeaderReader() {
if (isAbiVersionCompatible(version)) { super(KotlinClass.CLASS_NAME);
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + annotationClassName); }
}
private class PackageHeaderReader extends HeaderAnnotationArgumentVisitor {
public PackageHeaderReader() {
super(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE));
}
}
private class SyntheticClassHeaderReader extends HeaderAnnotationArgumentVisitor {
public SyntheticClassHeaderReader() {
super(KotlinSyntheticClass.CLASS_NAME);
}
@Override
public void visitEnum(@NotNull Name name, @NotNull ClassId enumClassId, @NotNull Name enumEntryName) {
if (enumClassId.equals(KotlinSyntheticClass.KIND_CLASS_ID) && name.asString().equals(KIND_FIELD_NAME)) {
syntheticClassKind = valueOfOrNull(KotlinSyntheticClass.Kind.class, enumEntryName.asString());
if (syntheticClassKind != null) return;
}
unexpectedEnumArgument(name, enumClassId, enumEntryName);
} }
return null;
} }
// This function is needed here because Enum.valueOf() throws exception if there's no such value, // This function is needed here because Enum.valueOf() throws exception if there's no such value,