diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java index 7be8112f25e..ca45bdbf7af 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java @@ -79,7 +79,7 @@ public class CliVirtualFileFinder implements VirtualFileFinder { return null; } //NOTE: currently we use VirtualFileFinder to find Kotlin binaries only - if (KotlinClassFileHeader.readKotlinHeaderFromClassFile(vFile).getType() != null) { + if (KotlinClassFileHeader.readKotlinHeaderFromClassFile(vFile) != null) { return vFile; } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java index 6258ffa260b..edd797e2dc0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DeserializedDescriptorResolver.java @@ -126,8 +126,11 @@ public final class DeserializedDescriptorResolver { @Nullable private String[] readData(@NotNull VirtualFile virtualFile) { KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile); + if (header == null) { + return null; + } int version = header.getVersion(); - if (!isAbiVersionCompatible(version) && header.getType() != null) { + if (!isAbiVersionCompatible(version)) { errorReporter.reportIncompatibleAbiVersion(header.getFqName(), virtualFile, version); return null; } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/KotlinClassFileHeader.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/KotlinClassFileHeader.java index 6f763a8ff54..028505d9a1c 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/KotlinClassFileHeader.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/KotlinClassFileHeader.java @@ -23,12 +23,19 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom public final class KotlinClassFileHeader { private static final Logger LOG = Logger.getInstance(KotlinClassFileHeader.class); - @NotNull + @Nullable public static KotlinClassFileHeader readKotlinHeaderFromClassFile(@NotNull VirtualFile virtualFile) { try { ClassReader reader = new ClassReader(virtualFile.contentsToByteArray()); ReadDataFromAnnotationVisitor visitor = new ReadDataFromAnnotationVisitor(); reader.accept(visitor, SKIP_CODE | SKIP_FRAMES | SKIP_DEBUG); + if (visitor.type == null) { + return null; + } + if (visitor.fqName == null) { + LOG.error("File doesn't have a class name: " + virtualFile); + return null; + } return new KotlinClassFileHeader(visitor.version, visitor.annotationData, visitor.type, visitor.fqName); } catch (IOException e) { @@ -70,14 +77,11 @@ public final class KotlinClassFileHeader { } private final int version; - @Nullable private final String[] annotationData; - @Nullable private final HeaderType type; - @Nullable private final FqName fqName; - private KotlinClassFileHeader(int version, @Nullable String[] annotationData, @Nullable HeaderType type, @Nullable FqName fqName) { + private KotlinClassFileHeader(int version, @Nullable String[] annotationData, @NotNull HeaderType type, @NotNull FqName fqName) { this.version = version; this.annotationData = annotationData; this.type = type; @@ -89,15 +93,17 @@ public final class KotlinClassFileHeader { } @Nullable - public HeaderType getType() { - return type; + public String[] getAnnotationData() { + if (isCompatibleKotlinCompiledFile() && annotationData == null) { + LOG.error("Kotlin annotation " + type + " is incorrect for class: " + fqName); + return null; + } + return annotationData; } - /** - * @return true if this is a header for compiled Kotlin file with correct abi version which can be processed by compiler or the IDE - */ - public boolean isCompatibleKotlinCompiledFile() { - return type != null && type.isValidAnnotation() && isAbiVersionCompatible(version); + @NotNull + public HeaderType getType() { + return type; } /** @@ -105,16 +111,14 @@ public final class KotlinClassFileHeader { */ @NotNull public FqName getFqName() { - assert fqName != null; return fqName; } - @Nullable - public String[] getAnnotationData() { - if (annotationData == null && type != null) { - LOG.error("Data for annotations " + type.correspondingAnnotation + " was not read."); - } - return annotationData; + /** + * @return true if this is a header for compiled Kotlin file with correct abi version which can be processed by compiler or the IDE + */ + public boolean isCompatibleKotlinCompiledFile() { + return type.isValidAnnotation() && isAbiVersionCompatible(version); } private static class ReadDataFromAnnotationVisitor extends ClassVisitor { diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java index dbfc745877e..2fae17dd058 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -102,17 +102,31 @@ public class JetFromJavaDescriptorHelper { @Nullable private static ClassData getClassData(@NotNull PsiClass psiClass) { VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass); - if (virtualFile == null) return null; - String[] data = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile).getAnnotationData(); - return data == null ? null : JavaProtoBufUtil.readClassDataFrom(data); + if (virtualFile != null) { + KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile); + if (header != null) { + String[] data = header.getAnnotationData(); + if (data != null) { + return JavaProtoBufUtil.readClassDataFrom(data); + } + } + } + return null; } @Nullable private static PackageData getPackageData(@NotNull PsiClass psiClass) { VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass); - if (virtualFile == null) return null; - String[] data = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile).getAnnotationData(); - return data == null ? null : JavaProtoBufUtil.readPackageDataFrom(data); + if (virtualFile != null) { + KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile); + if (header != null) { + String[] data = header.getAnnotationData(); + if (data != null) { + return JavaProtoBufUtil.readPackageDataFrom(data); + } + } + } + return null; } //TODO: common utility diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java index f414aa3e2c5..5b4ab264fb0 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -60,7 +60,10 @@ public final class DecompiledDataFactory { InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(project, new BindingTraceContext()); this.javaDescriptorResolver = injector.getJavaDescriptorResolver(); - this.kotlinClassFileHeader = KotlinClassFileHeader.readKotlinHeaderFromClassFile(classFile); + + KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(classFile); + assert header != null : "Decompiled data factory shouldn't be called on an unsupported file: " + classFile; + this.kotlinClassFileHeader = header; } @NotNull diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java index 6ee53e6a665..4867389adb7 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java @@ -28,7 +28,8 @@ public final class DecompiledUtils { return false; } //TODO: check index - return KotlinClassFileHeader.readKotlinHeaderFromClassFile(file).isCompatibleKotlinCompiledFile(); + KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(file); + return header != null && header.isCompatibleKotlinCompiledFile(); } private DecompiledUtils() { diff --git a/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java b/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java index 3a4a3aebf79..81f95500bfd 100644 --- a/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java +++ b/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java @@ -58,7 +58,7 @@ public final class KotlinClassFileIndex extends ScalarIndexExtension { public Map map(FileContent inputData) { try { KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(inputData.getFile()); - if (header.isCompatibleKotlinCompiledFile()) { + if (header != null && header.isCompatibleKotlinCompiledFile()) { return Collections.singletonMap(header.getFqName(), null); } }