Remove hack from AnnotationDescriptorDeserializer

Now that package fragment classes are generated to "*Package-filename-hash", we
can use virtualFileFinder to find such classes by FQ name. Support
KotlinPackageFragment annotation, by which VirtualFileFinder will determine
that a class was compiled by Kotlin compiler
This commit is contained in:
Alexander Udalov
2013-09-20 17:23:59 +04:00
parent fdc631d595
commit c5bed7a246
4 changed files with 81 additions and 31 deletions
@@ -92,7 +92,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
@NotNull
@Override
public List<AnnotationDescriptor> loadClassAnnotations(@NotNull ClassDescriptor descriptor, @NotNull ProtoBuf.Class classProto) {
VirtualFile virtualFile = findVirtualFileByClass(descriptor);
VirtualFile virtualFile = findVirtualFileByDescriptor(descriptor);
if (virtualFile == null) {
// This means that the resource we're constructing the descriptor from is no longer present: VirtualFileFinder had found the
// file earlier, but it can't now
@@ -111,26 +111,16 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
@Nullable
private VirtualFile findVirtualFileByDescriptor(@NotNull ClassOrNamespaceDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor) {
return findVirtualFileByClass((ClassDescriptor) descriptor);
return virtualFileFinder.find(kotlinFqNameToJavaFqName(naiveKotlinFqName((ClassDescriptor) descriptor)));
}
else if (descriptor instanceof NamespaceDescriptor) {
return findVirtualFileByPackage((NamespaceDescriptor) descriptor);
return virtualFileFinder.find(PackageClassUtils.getPackageClassFqName(DescriptorUtils.getFQName(descriptor).toSafe()));
}
else {
throw new IllegalStateException("Unrecognized descriptor: " + descriptor);
}
}
@Nullable
private VirtualFile findVirtualFileByClass(@NotNull ClassDescriptor descriptor) {
return virtualFileFinder.find(kotlinFqNameToJavaFqName(naiveKotlinFqName(descriptor)));
}
@Nullable
private VirtualFile findVirtualFileByPackage(@NotNull NamespaceDescriptor descriptor) {
return virtualFileFinder.find(PackageClassUtils.getPackageClassFqName(DescriptorUtils.getFQName(descriptor).toSafe()));
}
@NotNull
private List<AnnotationDescriptor> loadClassAnnotationsFromFile(@NotNull VirtualFile virtualFile) throws IOException {
final List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>();
@@ -250,15 +240,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
if (container instanceof NamespaceDescriptor) {
Name name = loadSrcClassName(proto, nameResolver);
if (name != null) {
// To locate a package$src class, we first find the facade virtual file (*Package.class) and then look up the $src file in
// the same directory. This hack is needed because FileManager doesn't find classfiles for $src classes
VirtualFile facadeFile = findVirtualFileByPackage((NamespaceDescriptor) container);
if (facadeFile != null) {
VirtualFile srcFile = facadeFile.getParent().findChild(name + ".class");
if (srcFile != null) {
return srcFile;
}
}
return virtualFileFinder.find(getSrcClassFqName((NamespaceDescriptor) container, name));
}
return null;
}
@@ -272,6 +254,11 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
return findVirtualFileByDescriptor(container);
}
@NotNull
private static FqName getSrcClassFqName(@NotNull NamespaceDescriptor container, @NotNull Name name) {
return PackageClassUtils.getPackageClassFqName(DescriptorUtils.getFQName(container).toSafe()).parent().child(name);
}
@Nullable
private static Name loadSrcClassName(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) {
return proto.hasExtension(JavaProtoBuf.srcClassName) ? nameResolver.getName(proto.getExtension(JavaProtoBuf.srcClassName)) : null;
@@ -0,0 +1,27 @@
/*
* 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.kotlin.header;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassFileHeader;
import org.jetbrains.jet.lang.resolve.name.FqName;
public class PackageFragmentClassFileHeader extends KotlinClassFileHeader {
protected PackageFragmentClassFileHeader(int version, @NotNull FqName fqName) {
super(version, fqName);
}
}
@@ -40,6 +40,7 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
private enum HeaderType {
CLASS(JvmAnnotationNames.KOTLIN_CLASS),
PACKAGE(JvmAnnotationNames.KOTLIN_PACKAGE),
PACKAGE_FRAGMENT(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT),
OLD_CLASS(JvmAnnotationNames.OLD_JET_CLASS_ANNOTATION),
OLD_PACKAGE(JvmAnnotationNames.OLD_JET_PACKAGE_CLASS_ANNOTATION);
@@ -93,6 +94,8 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
return serializedDataHeader(SerializedDataHeader.Kind.CLASS, fqName);
case PACKAGE:
return serializedDataHeader(SerializedDataHeader.Kind.PACKAGE, fqName);
case PACKAGE_FRAGMENT:
return new PackageFragmentClassFileHeader(version, fqName);
default:
throw new UnsupportedOperationException("Unknown compatible HeaderType: " + foundType);
}
@@ -127,6 +130,9 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) {
return kotlinClassOrPackageVisitor(desc);
}
else if (newType == HeaderType.PACKAGE_FRAGMENT) {
return kotlinPackageFragmentVisitor(desc);
}
return null;
}
@@ -136,12 +142,7 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
version = (Integer) value;
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc);
}
visitIntValueForSupportedAnnotation(name, value, desc);
}
@Override
@@ -177,4 +178,23 @@ import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCom
}
};
}
@NotNull
private AnnotationVisitor kotlinPackageFragmentVisitor(final String desc) {
return new AnnotationVisitor(Opcodes.ASM4) {
@Override
public void visit(String name, Object value) {
visitIntValueForSupportedAnnotation(name, value, desc);
}
};
}
private void visitIntValueForSupportedAnnotation(@NotNull String name, @NotNull Object value, @NotNull String desc) {
if (name.equals(JvmAnnotationNames.ABI_VERSION_FIELD_NAME)) {
version = (Integer) value;
}
else if (isAbiVersionCompatible(version)) {
throw new IllegalStateException("Unexpected argument " + name + " for annotation " + desc);
}
}
}