001 /*
002 * Copyright 2010-2014 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.kotlin;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.descriptors.serialization.JavaProtoBuf;
022 import org.jetbrains.jet.descriptors.serialization.NameResolver;
023 import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
024 import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotatedCallableKind;
025 import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor;
026 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
027 import org.jetbrains.jet.lang.descriptors.ClassOrPackageFragmentDescriptor;
028 import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
029 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
030 import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
031 import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
032 import org.jetbrains.jet.lang.resolve.name.Name;
033
034 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
035 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
036 import static org.jetbrains.jet.lang.resolve.kotlin.DescriptorLoadersStorage.MemberSignature;
037 import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
038 import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.naiveKotlinFqName;
039
040 public abstract class BaseDescriptorLoader {
041 protected KotlinClassFinder kotlinClassFinder;
042 protected ErrorReporter errorReporter;
043
044 protected DescriptorLoadersStorage storage;
045
046 public abstract void setKotlinClassFinder(@NotNull KotlinClassFinder kotlinClassFinder);
047
048 public abstract void setErrorReporter(@NotNull ErrorReporter errorReporter);
049
050 public abstract void setStorage(@NotNull DescriptorLoadersStorage storage);
051
052 @Nullable
053 protected static MemberSignature getCallableSignature(
054 @NotNull ProtoBuf.Callable proto,
055 @NotNull NameResolver nameResolver,
056 @NotNull AnnotatedCallableKind kind
057 ) {
058 SignatureDeserializer deserializer = new SignatureDeserializer(nameResolver);
059 switch (kind) {
060 case FUNCTION:
061 if (proto.hasExtension(JavaProtoBuf.methodSignature)) {
062 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.methodSignature));
063 }
064 break;
065 case PROPERTY_GETTER:
066 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
067 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.propertySignature).getGetter());
068 }
069 break;
070 case PROPERTY_SETTER:
071 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
072 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.propertySignature).getSetter());
073 }
074 break;
075 case PROPERTY:
076 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
077 JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature);
078
079 if (propertySignature.hasField()) {
080 JavaProtoBuf.JavaFieldSignature field = propertySignature.getField();
081 String type = deserializer.typeDescriptor(field.getType());
082 Name name = nameResolver.getName(field.getName());
083 return MemberSignature.fromFieldNameAndDesc(name, type);
084 }
085 else if (propertySignature.hasSyntheticMethod()) {
086 return deserializer.methodSignature(propertySignature.getSyntheticMethod());
087 }
088 }
089 break;
090 }
091 return null;
092 }
093
094 @Nullable
095 protected KotlinJvmBinaryClass findClassWithAnnotationsAndInitializers(
096 @NotNull ClassOrPackageFragmentDescriptor container,
097 @NotNull ProtoBuf.Callable proto,
098 @NotNull NameResolver nameResolver,
099 @NotNull AnnotatedCallableKind kind
100 ) {
101 if (container instanceof PackageFragmentDescriptor) {
102 return getPackagePartClassFqNameSafe((PackageFragmentDescriptor) container, proto, nameResolver);
103 }
104 else if (isClassObject(container) && isStaticFieldInOuter(proto)) {
105 // Backing fields of properties of a class object are generated in the outer class
106 return findKotlinClassByDescriptor((ClassOrPackageFragmentDescriptor) container.getContainingDeclaration());
107 }
108 else if (isTrait(container) && kind == AnnotatedCallableKind.PROPERTY) {
109 PackageFragmentDescriptor containingPackage = DescriptorUtils.getParentOfType(container, PackageFragmentDescriptor.class);
110 assert containingPackage != null : "Trait must have a package fragment among his parents: " + container;
111
112 if (proto.hasExtension(JavaProtoBuf.implClassName)) {
113 Name tImplName = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
114 return kotlinClassFinder.findKotlinClass(containingPackage.getFqName().child(tImplName));
115 }
116 return null;
117 }
118
119 return findKotlinClassByDescriptor(container);
120 }
121
122 @Nullable
123 private KotlinJvmBinaryClass getPackagePartClassFqNameSafe(
124 @NotNull PackageFragmentDescriptor container,
125 @NotNull ProtoBuf.Callable proto,
126 @NotNull NameResolver nameResolver
127 ) {
128 if (proto.hasExtension(JavaProtoBuf.implClassName)) {
129 return kotlinClassFinder.findKotlinClass(container.getFqName().child(getPackagePartClassName(proto, nameResolver)));
130 }
131 return null;
132 }
133
134 @NotNull
135 public static Name getPackagePartClassName(@NotNull DeserializedCallableMemberDescriptor deserializedCallableMember) {
136 return getPackagePartClassName(deserializedCallableMember.getProto(), deserializedCallableMember.getNameResolver());
137 }
138
139 @NotNull
140 private static Name getPackagePartClassName(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) {
141 return nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
142 }
143
144 private static boolean isStaticFieldInOuter(@NotNull ProtoBuf.Callable proto) {
145 if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return false;
146 JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature);
147 return propertySignature.hasField() && propertySignature.getField().getIsStaticInOuter();
148 }
149
150 @Nullable
151 protected KotlinJvmBinaryClass findKotlinClassByDescriptor(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
152 if (descriptor instanceof ClassDescriptor) {
153 return kotlinClassFinder.findKotlinClass(kotlinFqNameToJavaFqName(naiveKotlinFqName((ClassDescriptor) descriptor)));
154 }
155 else if (descriptor instanceof PackageFragmentDescriptor) {
156 return kotlinClassFinder.findKotlinClass(
157 PackageClassUtils.getPackageClassFqName(((PackageFragmentDescriptor) descriptor).getFqName()));
158 }
159 else {
160 throw new IllegalStateException("Unrecognized descriptor: " + descriptor);
161 }
162 }
163 }