Load annotations on properties declared in traits

This commit is contained in:
Alexander Udalov
2013-10-16 21:49:27 +04:00
parent 5a1daaa4b6
commit b7789da3b9
21 changed files with 204 additions and 53 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java;
import jet.KotlinClass;
import jet.KotlinPackage;
import jet.KotlinPackageFragment;
import jet.KotlinTraitImpl;
import org.jetbrains.jet.lang.resolve.name.FqName;
import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.fqNameByClass;
@@ -30,6 +31,8 @@ public final class JvmAnnotationNames {
public static final FqName KOTLIN_PACKAGE_FRAGMENT = fqNameByClass(KotlinPackageFragment.class);
public static final FqName KOTLIN_TRAIT_IMPL = fqNameByClass(KotlinTraitImpl.class);
public static final String ABI_VERSION_FIELD_NAME = "abiVersion";
public static final String DATA_FIELD_NAME = "data";
@@ -47,6 +47,8 @@ import javax.inject.Inject;
import java.io.IOException;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.naiveKotlinFqName;
@@ -231,7 +233,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
MemberSignature signature = getCallableSignature(proto, nameResolver, kind);
if (signature == null) return Collections.emptyList();
KotlinJvmBinaryClass kotlinClass = findClassWithMemberAnnotations(container, proto, nameResolver);
KotlinJvmBinaryClass kotlinClass = findClassWithMemberAnnotations(container, proto, nameResolver, kind);
if (kotlinClass == null) {
errorReporter.reportAnnotationLoadingError("Kotlin class for loading member annotations is not found: " + container, null);
return Collections.emptyList();
@@ -245,33 +247,42 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer
private KotlinJvmBinaryClass findClassWithMemberAnnotations(
@NotNull ClassOrNamespaceDescriptor container,
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver
@NotNull NameResolver nameResolver,
@NotNull AnnotatedCallableKind kind
) {
if (container instanceof NamespaceDescriptor) {
Name name = loadSrcClassName(proto, nameResolver);
if (name != null) {
return kotlinClassFinder.find(getSrcClassFqName((NamespaceDescriptor) container, name));
return loadPackageFragmentClassFqName((NamespaceDescriptor) container, proto, nameResolver);
}
else if (isClassObject(container) && isStaticFieldInOuter(proto)) {
// Backing fields of properties of a class object are generated in the outer class
return findKotlinClassByDescriptor((ClassOrNamespaceDescriptor) container.getContainingDeclaration());
}
else if (isTrait(container) && kind == AnnotatedCallableKind.PROPERTY) {
NamespaceDescriptor containingPackage = DescriptorUtils.getParentOfType(container, NamespaceDescriptor.class);
assert containingPackage != null : "Trait must have a namespace among his parents: " + container;
if (proto.hasExtension(JavaProtoBuf.implClassName)) {
Name tImplName = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
return kotlinClassFinder.find(containingPackage.getFqName().child(tImplName));
}
return null;
}
else if (container instanceof ClassDescriptor && ((ClassDescriptor) container).getKind() == ClassKind.CLASS_OBJECT) {
// Backing fields of properties of a class object are generated in the outer class
if (isStaticFieldInOuter(proto)) {
return findKotlinClassByDescriptor((ClassOrNamespaceDescriptor) container.getContainingDeclaration());
}
}
return findKotlinClassByDescriptor(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;
private KotlinJvmBinaryClass loadPackageFragmentClassFqName(
@NotNull NamespaceDescriptor container,
@NotNull ProtoBuf.Callable proto,
@NotNull NameResolver nameResolver
) {
if (proto.hasExtension(JavaProtoBuf.implClassName)) {
Name name = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
FqName fqName = PackageClassUtils.getPackageClassFqName(container.getFqName()).parent().child(name);
return kotlinClassFinder.find(fqName);
}
return null;
}
private static boolean isStaticFieldInOuter(@NotNull ProtoBuf.Callable proto) {
@@ -38,6 +38,7 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat
CLASS(JvmAnnotationNames.KOTLIN_CLASS),
PACKAGE(JvmAnnotationNames.KOTLIN_PACKAGE),
PACKAGE_FRAGMENT(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT),
TRAIT_IMPL(JvmAnnotationNames.KOTLIN_TRAIT_IMPL),
OLD_CLASS(JvmAnnotationNames.OLD_JET_CLASS_ANNOTATION),
OLD_PACKAGE(JvmAnnotationNames.OLD_JET_PACKAGE_CLASS_ANNOTATION);
@@ -92,6 +93,8 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat
return serializedDataHeader(SerializedDataHeader.Kind.PACKAGE);
case PACKAGE_FRAGMENT:
return new PackageFragmentClassHeader(version);
case TRAIT_IMPL:
return new TraitImplClassHeader(version);
default:
throw new UnsupportedOperationException("Unknown compatible HeaderType: " + foundType);
}
@@ -123,8 +126,8 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat
if (newType == HeaderType.CLASS || newType == HeaderType.PACKAGE) {
return kotlinClassOrPackageVisitor(annotationClassName);
}
else if (newType == HeaderType.PACKAGE_FRAGMENT) {
return kotlinPackageFragmentVisitor(annotationClassName);
else if (newType == HeaderType.PACKAGE_FRAGMENT || newType == HeaderType.TRAIT_IMPL) {
return annotationWithAbiVersionVisitor(annotationClassName);
}
return null;
@@ -198,7 +201,7 @@ import static org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass.Annotat
}
@NotNull
private AnnotationArgumentVisitor kotlinPackageFragmentVisitor(@NotNull final JvmClassName annotationClassName) {
private AnnotationArgumentVisitor annotationWithAbiVersionVisitor(@NotNull final JvmClassName annotationClassName) {
return new AnnotationArgumentVisitor() {
@Override
public void visit(@Nullable Name name, @Nullable Object value) {
@@ -0,0 +1,23 @@
/*
* 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;
/* package */ class TraitImplClassHeader extends KotlinClassHeader {
protected TraitImplClassHeader(int version) {
super(version);
}
}