Rework invalid abi version reporting
KotlinClassFileHeader is aware of older annotations Psi is not used to report invalid Abi version in CLI
This commit is contained in:
@@ -16,26 +16,60 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
|
||||
import org.jetbrains.jet.util.slicedmap.Slices;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
|
||||
public class AbiVersionUtil {
|
||||
public static final WritableSlice<PsiClass, Integer> ABI_VERSION_ERRORS =
|
||||
new BasicWritableSlice<PsiClass, Integer>(Slices.ONLY_REWRITE_TO_EQUAL, true);
|
||||
public final class AbiVersionUtil {
|
||||
public static final WritableSlice<AbiVersionErrorLocation, Integer> ABI_VERSION_ERRORS =
|
||||
new BasicWritableSlice<AbiVersionErrorLocation, Integer>(Slices.ONLY_REWRITE_TO_EQUAL, true);
|
||||
public static final int INVALID_VERSION = -1;
|
||||
|
||||
private AbiVersionUtil() {
|
||||
}
|
||||
|
||||
public static boolean isAbiVersionCompatible(int abiVersion) {
|
||||
return abiVersion == JvmAbi.VERSION;
|
||||
}
|
||||
|
||||
public static void reportIncompatibleAbiVersion(@NotNull PsiClass psiClass, int version, @NotNull BindingTrace trace) {
|
||||
trace.record(ABI_VERSION_ERRORS, psiClass, version);
|
||||
@NotNull
|
||||
public static ErrorReporter abiVersionErrorReporter(
|
||||
@NotNull final VirtualFile file,
|
||||
@NotNull final FqName classFqName,
|
||||
@NotNull final BindingTrace trace
|
||||
) {
|
||||
return new ErrorReporter() {
|
||||
@Override
|
||||
public void reportIncompatibleAbiVersion(int actualVersion) {
|
||||
trace.record(ABI_VERSION_ERRORS, new AbiVersionErrorLocation(classFqName, file), actualVersion);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static final class AbiVersionErrorLocation {
|
||||
@NotNull
|
||||
private final FqName classFqName;
|
||||
@NotNull
|
||||
private final VirtualFile file;
|
||||
|
||||
public AbiVersionErrorLocation(@NotNull FqName name, @NotNull VirtualFile file) {
|
||||
this.classFqName = name;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName getClassFqName() {
|
||||
return classFqName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPath() {
|
||||
return file.getPath();
|
||||
}
|
||||
}
|
||||
|
||||
private AbiVersionUtil() {
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -23,8 +23,6 @@ import com.intellij.psi.util.PsiFormatUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -138,16 +136,6 @@ public final class DescriptorResolverUtils {
|
||||
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ErrorReporter createPsiBasedErrorReporter(@NotNull final PsiClass psiClass, @NotNull final BindingTrace trace) {
|
||||
return new ErrorReporter() {
|
||||
@Override
|
||||
public void reportIncompatibleAbiVersion(int actualVersion) {
|
||||
AbiVersionUtil.reportIncompatibleAbiVersion(psiClass, actualVersion, trace);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean isObjectMethodInInterface(@NotNull PsiMember member) {
|
||||
if (!(member instanceof PsiMethod)) {
|
||||
return false;
|
||||
|
||||
+5
-8
@@ -131,15 +131,12 @@ public final class DeserializedDescriptorResolver {
|
||||
|
||||
@Nullable
|
||||
private static String[] readData(@NotNull VirtualFile virtualFile, @NotNull ErrorReporter reporter) {
|
||||
KotlinClassFileHeader headerData = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile);
|
||||
int version = headerData.getVersion();
|
||||
String[] annotationData = headerData.getAnnotationData();
|
||||
if (isAbiVersionCompatible(version)) {
|
||||
return annotationData;
|
||||
}
|
||||
if (annotationData != null) {
|
||||
KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile);
|
||||
int version = header.getVersion();
|
||||
if (!isAbiVersionCompatible(version) && header.getType() != KotlinClassFileHeader.HeaderType.NONE) {
|
||||
reporter.reportIncompatibleAbiVersion(version);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
return header.getAnnotationData();
|
||||
}
|
||||
}
|
||||
|
||||
+39
-16
@@ -21,6 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.asm4.ClassReader.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
|
||||
|
||||
public final class KotlinClassFileHeader {
|
||||
@NotNull
|
||||
@@ -42,9 +43,12 @@ public final class KotlinClassFileHeader {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public enum HeaderType {
|
||||
CLASS(JvmAnnotationNames.KOTLIN_CLASS),
|
||||
PACKAGE(JvmAnnotationNames.KOTLIN_PACKAGE),
|
||||
OLD_CLASS(JvmAnnotationNames.OLD_JET_CLASS_ANNOTATION),
|
||||
OLD_PACKAGE(JvmAnnotationNames.OLD_JET_PACKAGE_CLASS_ANNOTATION),
|
||||
NONE(null);
|
||||
|
||||
@Nullable
|
||||
@@ -53,6 +57,24 @@ public final class KotlinClassFileHeader {
|
||||
HeaderType(@Nullable JvmClassName annotation) {
|
||||
correspondingAnnotation = annotation;
|
||||
}
|
||||
|
||||
boolean isValidAnnotation() {
|
||||
return this == CLASS || this == PACKAGE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HeaderType byDescriptor(@NotNull String desc) {
|
||||
for (HeaderType headerType : HeaderType.values()) {
|
||||
JvmClassName annotation = headerType.correspondingAnnotation;
|
||||
if (annotation == null) {
|
||||
continue;
|
||||
}
|
||||
if (desc.equals(annotation.getDescriptor())) {
|
||||
return headerType;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
private int version = AbiVersionUtil.INVALID_VERSION;
|
||||
@@ -73,8 +95,11 @@ public final class KotlinClassFileHeader {
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
Checks that this is a header for compiled Kotlin file with correct abi version which can be processed by compiler or the IDE.
|
||||
*/
|
||||
public boolean isKotlinCompiledFile() {
|
||||
return type != HeaderType.NONE;
|
||||
return type.isValidAnnotation() && isAbiVersionCompatible(version);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -119,20 +144,18 @@ public final class KotlinClassFileHeader {
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
for (HeaderType headerType : HeaderType.values()) {
|
||||
JvmClassName annotation = headerType.correspondingAnnotation;
|
||||
if (annotation == null) {
|
||||
continue;
|
||||
}
|
||||
if (desc.equals(annotation.getDescriptor())) {
|
||||
if (type != HeaderType.NONE) {
|
||||
throw new IllegalStateException(
|
||||
"Both " + type.correspondingAnnotation + " and " + headerType.correspondingAnnotation + " present!");
|
||||
}
|
||||
type = headerType;
|
||||
}
|
||||
HeaderType headerTypeByAnnotation = HeaderType.byDescriptor(desc);
|
||||
if (headerTypeByAnnotation == HeaderType.NONE) {
|
||||
return null;
|
||||
}
|
||||
if (type == HeaderType.NONE) {
|
||||
if (headerTypeByAnnotation.isValidAnnotation() && type.isValidAnnotation()) {
|
||||
throw new IllegalStateException("Both " + type.correspondingAnnotation + " and "
|
||||
+ headerTypeByAnnotation.correspondingAnnotation + " present!");
|
||||
}
|
||||
if (!type.isValidAnnotation()) {
|
||||
type = headerTypeByAnnotation;
|
||||
}
|
||||
if (!headerTypeByAnnotation.isValidAnnotation()) {
|
||||
return null;
|
||||
}
|
||||
return new AnnotationVisitor(Opcodes.ASM4) {
|
||||
@@ -141,7 +164,7 @@ public final class KotlinClassFileHeader {
|
||||
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
|
||||
version = (Integer) value;
|
||||
}
|
||||
else if (AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||
else if (isAbiVersionCompatible(version)) {
|
||||
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc);
|
||||
}
|
||||
}
|
||||
@@ -151,7 +174,7 @@ public final class KotlinClassFileHeader {
|
||||
if (name.equals(JvmAnnotationNames.DATA_FIELD_NAME)) {
|
||||
return stringArrayVisitor();
|
||||
}
|
||||
else if (AbiVersionUtil.isAbiVersionCompatible(version)) {
|
||||
else if (isAbiVersionCompatible(version)) {
|
||||
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + desc);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user