Store ABI version along with serialized descriptors
KotlinInfo annotation now has a version() field, which should be equal to the compiler's JvmAbi.VERSION in order for this class to properly load and be used. Create ErrorReporter class, which has a trace to which it can report errors (now only related to ABI version). This is done because a dependency of DeserializedDescriptorResolver from BindingTrace would be confusing. Implementation of ErrorReporter will probably need to change when we untie deserialization from java-resolve. Check if PsiClass is actually a compiled class before trying to load serialized data from it: otherwise it can be a Java source, as was in wrongAbiVersion() test, and ASM will fail when trying to read that file. Rewrite the test so that it now has a compiled Kotlin classes to check against (also include sources to recompile this binary data later, although it won't probably be needed)
This commit is contained in:
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver;
|
||||
@@ -64,6 +65,7 @@ public class InjectorForJavaDescriptorResolver {
|
||||
private final JavaSignatureResolver javaSignatureResolver;
|
||||
private final DeserializedDescriptorResolver deserializedDescriptorResolver;
|
||||
private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final JavaNamespaceResolver javaNamespaceResolver;
|
||||
private final JavaConstructorResolver javaConstructorResolver;
|
||||
private final JavaInnerClassResolver javaInnerClassResolver;
|
||||
@@ -93,6 +95,7 @@ public class InjectorForJavaDescriptorResolver {
|
||||
this.javaSignatureResolver = new JavaSignatureResolver();
|
||||
this.deserializedDescriptorResolver = new DeserializedDescriptorResolver();
|
||||
this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer();
|
||||
this.errorReporter = new ErrorReporter();
|
||||
this.javaNamespaceResolver = new JavaNamespaceResolver();
|
||||
this.javaConstructorResolver = new JavaConstructorResolver();
|
||||
this.javaInnerClassResolver = new JavaInnerClassResolver();
|
||||
@@ -155,12 +158,15 @@ public class InjectorForJavaDescriptorResolver {
|
||||
javaSignatureResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
|
||||
deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer);
|
||||
deserializedDescriptorResolver.setErrorReporter(errorReporter);
|
||||
deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver);
|
||||
deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver);
|
||||
|
||||
annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver);
|
||||
annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
errorReporter.setTrace(bindingTrace);
|
||||
|
||||
javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver);
|
||||
javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
javaNamespaceResolver.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver;
|
||||
@@ -64,6 +65,7 @@ public class InjectorForJavaSemanticServices {
|
||||
private final JavaSignatureResolver javaSignatureResolver;
|
||||
private final DeserializedDescriptorResolver deserializedDescriptorResolver;
|
||||
private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final JavaNamespaceResolver javaNamespaceResolver;
|
||||
private final JavaConstructorResolver javaConstructorResolver;
|
||||
private final JavaInnerClassResolver javaInnerClassResolver;
|
||||
@@ -91,6 +93,7 @@ public class InjectorForJavaSemanticServices {
|
||||
this.javaSignatureResolver = new JavaSignatureResolver();
|
||||
this.deserializedDescriptorResolver = new DeserializedDescriptorResolver();
|
||||
this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer();
|
||||
this.errorReporter = new ErrorReporter();
|
||||
this.javaNamespaceResolver = new JavaNamespaceResolver();
|
||||
this.javaConstructorResolver = new JavaConstructorResolver();
|
||||
this.javaInnerClassResolver = new JavaInnerClassResolver();
|
||||
@@ -155,12 +158,15 @@ public class InjectorForJavaSemanticServices {
|
||||
javaSignatureResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
|
||||
deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer);
|
||||
deserializedDescriptorResolver.setErrorReporter(errorReporter);
|
||||
deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver);
|
||||
deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver);
|
||||
|
||||
annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver);
|
||||
annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
errorReporter.setTrace(bindingTrace);
|
||||
|
||||
javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver);
|
||||
javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
javaNamespaceResolver.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaSignatureResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaInnerClassResolver;
|
||||
@@ -114,6 +115,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
|
||||
private final JavaSignatureResolver javaSignatureResolver;
|
||||
private final DeserializedDescriptorResolver deserializedDescriptorResolver;
|
||||
private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final JavaNamespaceResolver javaNamespaceResolver;
|
||||
private final JavaConstructorResolver javaConstructorResolver;
|
||||
private final JavaInnerClassResolver javaInnerClassResolver;
|
||||
@@ -169,6 +171,7 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
|
||||
this.javaSignatureResolver = new JavaSignatureResolver();
|
||||
this.deserializedDescriptorResolver = new DeserializedDescriptorResolver();
|
||||
this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer();
|
||||
this.errorReporter = new ErrorReporter();
|
||||
this.javaNamespaceResolver = new JavaNamespaceResolver();
|
||||
this.javaConstructorResolver = new JavaConstructorResolver();
|
||||
this.javaInnerClassResolver = new JavaInnerClassResolver();
|
||||
@@ -333,12 +336,15 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
|
||||
javaSignatureResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
|
||||
deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer);
|
||||
deserializedDescriptorResolver.setErrorReporter(errorReporter);
|
||||
deserializedDescriptorResolver.setJavaClassResolver(javaClassResolver);
|
||||
deserializedDescriptorResolver.setJavaNamespaceResolver(javaNamespaceResolver);
|
||||
|
||||
annotationDescriptorDeserializer.setJavaClassResolver(javaClassResolver);
|
||||
annotationDescriptorDeserializer.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
errorReporter.setTrace(bindingTrace);
|
||||
|
||||
javaNamespaceResolver.setDeserializedDescriptorResolver(deserializedDescriptorResolver);
|
||||
javaNamespaceResolver.setJavaSemanticServices(javaSemanticServices);
|
||||
javaNamespaceResolver.setPsiClassFinder(psiClassFinder);
|
||||
|
||||
+10
-10
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.java;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithAbiVersion;
|
||||
import org.jetbrains.jet.util.slicedmap.BasicWritableSlice;
|
||||
import org.jetbrains.jet.util.slicedmap.Slices;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
@@ -29,19 +28,20 @@ public class AbiVersionUtil {
|
||||
new BasicWritableSlice<PsiClass, 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 checkAbiVersion(
|
||||
@NotNull PsiClass psiClass,
|
||||
@NotNull PsiAnnotationWithAbiVersion versionAnnotation,
|
||||
@NotNull BindingTrace trace) {
|
||||
if (!versionAnnotation.isDefined()) return;
|
||||
public static void checkAbiVersion(@NotNull PsiClass psiClass, int version, @NotNull BindingTrace trace) {
|
||||
if (!isAbiVersionCompatible(version)) {
|
||||
reportIncompatibleAbiVersion(psiClass, version, trace);
|
||||
}
|
||||
}
|
||||
|
||||
int abiVersion = versionAnnotation.getAbiVersion();
|
||||
if (isAbiVersionCompatible(abiVersion)) return;
|
||||
|
||||
trace.record(ABI_VERSION_ERRORS, psiClass, abiVersion);
|
||||
public static void reportIncompatibleAbiVersion(@NotNull PsiClass psiClass, int version, @NotNull BindingTrace trace) {
|
||||
trace.record(ABI_VERSION_ERRORS, psiClass, version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class JvmAbi {
|
||||
* This constant is used to identify binary format (class file) versions
|
||||
* If you change class file metadata format and/or naming conventions, please increase this number
|
||||
*/
|
||||
public static final int VERSION = 6;
|
||||
public static final int VERSION = 7;
|
||||
|
||||
public static final String TRAIT_IMPL_CLASS_NAME = "$TImpl";
|
||||
public static final String TRAIT_IMPL_SUFFIX = "$" + TRAIT_IMPL_CLASS_NAME;
|
||||
|
||||
+57
-28
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
@@ -44,6 +45,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;
|
||||
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN;
|
||||
import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.getVirtualFile;
|
||||
import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
|
||||
@@ -59,6 +61,8 @@ public final class DeserializedDescriptorResolver {
|
||||
|
||||
private JavaClassResolver javaClassResolver;
|
||||
|
||||
private ErrorReporter errorReporter;
|
||||
|
||||
@NotNull
|
||||
private final DescriptorFinder javaDescriptorFinder = new DescriptorFinder() {
|
||||
@Nullable
|
||||
@@ -89,6 +93,11 @@ public final class DeserializedDescriptorResolver {
|
||||
this.javaClassResolver = javaClassResolver;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setErrorReporter(ErrorReporter errorReporter) {
|
||||
this.errorReporter = errorReporter;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor resolveClass(
|
||||
@NotNull FqName fqName,
|
||||
@@ -97,28 +106,25 @@ public final class DeserializedDescriptorResolver {
|
||||
) {
|
||||
VirtualFile virtualFile = getVirtualFile(psiClass, fqName, containingDeclaration);
|
||||
if (virtualFile == null) {
|
||||
// TODO: use ErrorReporter here
|
||||
return null;
|
||||
}
|
||||
ClassData classData = readClassDataFromClassFile(virtualFile);
|
||||
ClassData classData = readClassDataFromClassFile(virtualFile, psiClass);
|
||||
if (classData == null) {
|
||||
return null;
|
||||
}
|
||||
return deserializeClass(classData, fqName, containingDeclaration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetScope createKotlinPackageScope(
|
||||
@NotNull FqName fqName,
|
||||
@NotNull PsiClass kotlinPackagePsiClass,
|
||||
@NotNull NamespaceDescriptor packageDescriptor
|
||||
) {
|
||||
@Nullable
|
||||
public JetScope createKotlinPackageScope(@NotNull PsiClass kotlinPackagePsiClass, @NotNull NamespaceDescriptor packageDescriptor) {
|
||||
VirtualFile virtualFile = kotlinPackagePsiClass.getContainingFile().getVirtualFile();
|
||||
if (virtualFile == null) {
|
||||
throw new IllegalStateException("Could not find virtual file for " + fqName.asString());
|
||||
return null;
|
||||
}
|
||||
PackageData packageData = readPackageDataFromClassFile(virtualFile);
|
||||
PackageData packageData = readPackageDataFromClassFile(virtualFile, kotlinPackagePsiClass);
|
||||
if (packageData == null) {
|
||||
throw new IllegalStateException("No KotlinInfo annotation stored for " + fqName.asString());
|
||||
return null;
|
||||
}
|
||||
return DeserializedPackageMemberScope.createScopeFromPackageData(packageDescriptor, packageData, javaDescriptorFinder,
|
||||
annotationDeserializer, storageManager);
|
||||
@@ -143,33 +149,32 @@ public final class DeserializedDescriptorResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ClassData readClassDataFromClassFile(@NotNull VirtualFile virtualFile) {
|
||||
String[] data = getKotlinInfoDataFromClassFile(virtualFile);
|
||||
if (data == null) return null;
|
||||
return JavaProtoBufUtil.readClassDataFrom(data);
|
||||
private ClassData readClassDataFromClassFile(@NotNull VirtualFile virtualFile, @NotNull PsiClass psiClass) {
|
||||
String[] data = readData(virtualFile, psiClass);
|
||||
return data == null ? null : JavaProtoBufUtil.readClassDataFrom(data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PackageData readPackageDataFromClassFile(@NotNull VirtualFile virtualFile) {
|
||||
String[] data = getKotlinInfoDataFromClassFile(virtualFile);
|
||||
if (data == null) return null;
|
||||
return JavaProtoBufUtil.readPackageDataFrom(data);
|
||||
private PackageData readPackageDataFromClassFile(@NotNull VirtualFile virtualFile, @NotNull PsiClass psiClass) {
|
||||
String[] data = readData(virtualFile, psiClass);
|
||||
return data == null ? null : JavaProtoBufUtil.readPackageDataFrom(data);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String[] getKotlinInfoDataFromClassFile(@NotNull VirtualFile virtualFile) {
|
||||
private String[] readData(@NotNull VirtualFile virtualFile, @NotNull PsiClass psiClass) {
|
||||
GetKotlinInfoDataVisitor visitor = visitClassFile(virtualFile);
|
||||
if (visitor == null) {
|
||||
return null;
|
||||
}
|
||||
int version = visitor.getVersion();
|
||||
String[] data = visitor.getData();
|
||||
if (data == null) {
|
||||
return null;
|
||||
if (isAbiVersionCompatible(version)) {
|
||||
return data;
|
||||
}
|
||||
return data;
|
||||
if (data != null) {
|
||||
errorReporter.reportIncompatibleAbiVersion(psiClass, version);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
private static GetKotlinInfoDataVisitor visitClassFile(@NotNull VirtualFile virtualFile) {
|
||||
try {
|
||||
InputStream inputStream = virtualFile.getInputStream();
|
||||
@@ -193,6 +198,8 @@ public final class DeserializedDescriptorResolver {
|
||||
super(Opcodes.ASM4);
|
||||
}
|
||||
|
||||
private int version = AbiVersionUtil.INVALID_VERSION;
|
||||
|
||||
@Nullable
|
||||
private String[] data = null;
|
||||
|
||||
@@ -204,11 +211,29 @@ public final class DeserializedDescriptorResolver {
|
||||
|
||||
return new AnnotationVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
if (!name.equals("data")) {
|
||||
public void visit(String name, Object value) {
|
||||
if (name.equals("version")) {
|
||||
version = (Integer) value;
|
||||
}
|
||||
else if (isAbiVersionCompatible(version)) {
|
||||
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + KOTLIN_INFO_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String name) {
|
||||
if (name.equals("data")) {
|
||||
return stringArrayVisitor();
|
||||
}
|
||||
else if (isAbiVersionCompatible(version)) {
|
||||
throw new IllegalStateException("Unexpected array argument " + name + " for annotation " + KOTLIN_INFO_TYPE);
|
||||
}
|
||||
|
||||
return super.visitArray(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotationVisitor stringArrayVisitor() {
|
||||
final List<String> strings = new ArrayList<String>(1);
|
||||
return new AnnotationVisitor(Opcodes.ASM4) {
|
||||
@Override
|
||||
@@ -229,6 +254,10 @@ public final class DeserializedDescriptorResolver {
|
||||
};
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String[] getData() {
|
||||
return data;
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.resolver;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class ErrorReporter {
|
||||
private BindingTrace trace;
|
||||
|
||||
@Inject
|
||||
public void setTrace(BindingTrace trace) {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
public void reportIncompatibleAbiVersion(@NotNull PsiClass psiClass, int version) {
|
||||
AbiVersionUtil.reportIncompatibleAbiVersion(psiClass, version, trace);
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -237,7 +237,6 @@ public final class JavaClassResolver {
|
||||
@NotNull FqName fqName, @NotNull PsiClass psiClass,
|
||||
@NotNull PostponedTasks taskList
|
||||
) {
|
||||
|
||||
checkFqNamesAreConsistent(psiClass, fqName);
|
||||
DescriptorResolverUtils.checkPsiClassIsNotJet(psiClass);
|
||||
|
||||
@@ -267,7 +266,9 @@ public final class JavaClassResolver {
|
||||
@NotNull ClassOrNamespaceDescriptor containingDeclaration
|
||||
) {
|
||||
JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass);
|
||||
AbiVersionUtil.checkAbiVersion(psiClass, jetClassAnnotation, trace);
|
||||
if (jetClassAnnotation.isDefined()) {
|
||||
AbiVersionUtil.checkAbiVersion(psiClass, jetClassAnnotation.getAbiVersion(), trace);
|
||||
}
|
||||
|
||||
ClassKind kind = getClassKind(psiClass, jetClassAnnotation);
|
||||
ClassPsiDeclarationProvider classData = semanticServices.getPsiDeclarationProviderFactory().createBinaryClassData(psiClass);
|
||||
|
||||
+33
-15
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java.resolver;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -36,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.java.provider.MembersCache;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaBaseScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaClassStaticMembersScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScopeWithoutMembers;
|
||||
import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
|
||||
@@ -44,6 +46,8 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.INVALID_VERSION;
|
||||
|
||||
public final class JavaNamespaceResolver {
|
||||
|
||||
@NotNull
|
||||
@@ -160,12 +164,24 @@ public final class JavaNamespaceResolver {
|
||||
if (psiPackage != null) {
|
||||
PsiClass psiClass = getPsiClassForJavaPackageScope(fqName);
|
||||
trace.record(JavaBindingContext.JAVA_NAMESPACE_KIND, namespaceDescriptor, JavaNamespaceKind.PROPER);
|
||||
if (psiClass == null || !isCompiledKotlinClass(psiClass)) {
|
||||
return new JavaPackageScopeWithoutMembers(namespaceDescriptor, javaSemanticServices.getPsiDeclarationProviderFactory()
|
||||
.createDeclarationProviderForNamespaceWithoutMembers(psiPackage), fqName, javaSemanticServices);
|
||||
|
||||
if (psiClass != null) {
|
||||
boolean compiledKotlinClass = isCompiledKotlinClass(psiClass);
|
||||
if (isOldKotlinPackageClass(psiClass) && !compiledKotlinClass) {
|
||||
// If psiClass has old annotations (@JetPackage) but doesn't have @KotlinInfo, report ABI version error
|
||||
AbiVersionUtil.checkAbiVersion(psiClass, INVALID_VERSION, trace);
|
||||
}
|
||||
if (compiledKotlinClass) {
|
||||
// If psiClass has @KotlinInfo (regardless of whether it has @JetPackage or not), deserialize it to Kotlin descriptor.
|
||||
// Note that @KotlinInfo may still have an old ABI version, in which case null is returned by createKotlinPackageScope
|
||||
JetScope kotlinPackageScope = deserializedDescriptorResolver.createKotlinPackageScope(psiClass, namespaceDescriptor);
|
||||
if (kotlinPackageScope != null) return kotlinPackageScope;
|
||||
}
|
||||
}
|
||||
|
||||
return createScopeForKotlinPackageClass(fqName, namespaceDescriptor, psiClass);
|
||||
// Otherwise (if psiClass is null or doesn't have a supported Kotlin annotation), it's a Java class and the package is empty
|
||||
return new JavaPackageScopeWithoutMembers(namespaceDescriptor, javaSemanticServices.getPsiDeclarationProviderFactory()
|
||||
.createDeclarationProviderForNamespaceWithoutMembers(psiPackage), fqName, javaSemanticServices);
|
||||
}
|
||||
|
||||
PsiClass psiClass = psiClassFinder.findPsiClass(fqName, PsiClassFinder.RuntimeClassesHandleMode.IGNORE);
|
||||
@@ -185,19 +201,21 @@ public final class JavaNamespaceResolver {
|
||||
fqName, javaSemanticServices);
|
||||
}
|
||||
|
||||
private static boolean isCompiledKotlinClass(@NotNull PsiClass psiClass) {
|
||||
PsiModifierList list = psiClass.getModifierList();
|
||||
return list != null && list.findAnnotation(JvmStdlibNames.KOTLIN_INFO_CLASS.getFqName().asString()) != null;
|
||||
private static boolean isOldKotlinPackageClass(@NotNull PsiClass psiClass) {
|
||||
return new PsiClassWrapper(psiClass).getJetPackageClass().isDefined();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetScope createScopeForKotlinPackageClass(
|
||||
@NotNull FqName fqName,
|
||||
@NotNull NamespaceDescriptor namespaceDescriptor,
|
||||
@NotNull PsiClass psiClass
|
||||
) {
|
||||
//TODO: check abi version
|
||||
return deserializedDescriptorResolver.createKotlinPackageScope(fqName, psiClass, namespaceDescriptor);
|
||||
private static boolean isCompiledKotlinClass(@NotNull PsiClass psiClass) {
|
||||
// TODO: merge this method with DescriptorResolverUtils#isKotlinClass
|
||||
// NOTE: we need to check against ClsClassImpl because it can be a Java source, pretending to be a Kotlin class.
|
||||
// In that case we can't really read the annotation from psiClass's virtual file
|
||||
if (psiClass instanceof ClsClassImpl) {
|
||||
PsiModifierList list = psiClass.getModifierList();
|
||||
if (list != null) {
|
||||
return list.findAnnotation(JvmStdlibNames.KOTLIN_INFO_CLASS.getFqName().asString()) != null;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void cache(@NotNull FqName fqName, @Nullable JetScope packageScope) {
|
||||
|
||||
Reference in New Issue
Block a user