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.DeserializedCallableMemberDescriptor;
025 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
026 import org.jetbrains.jet.lang.descriptors.ClassOrPackageFragmentDescriptor;
027 import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor;
028 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
029 import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
030 import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
031 import org.jetbrains.jet.lang.resolve.name.Name;
032 import org.jetbrains.jet.lang.types.DependencyClassByQualifiedNameResolver;
033
034 import static org.jetbrains.jet.descriptors.serialization.descriptors.Deserializers.AnnotatedCallableKind;
035 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
036 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTrait;
037 import static org.jetbrains.jet.lang.resolve.kotlin.DescriptorDeserializersStorage.MemberSignature;
038 import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
039 import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.naiveKotlinFqName;
040
041 public abstract class BaseDescriptorDeserializer {
042 protected DependencyClassByQualifiedNameResolver classResolver;
043 protected KotlinClassFinder kotlinClassFinder;
044 protected ErrorReporter errorReporter;
045
046 protected DescriptorDeserializersStorage storage;
047
048 public abstract void setClassResolver(@NotNull DependencyClassByQualifiedNameResolver classResolver);
049
050 public abstract void setKotlinClassFinder(@NotNull KotlinClassFinder kotlinClassFinder);
051
052 public abstract void setErrorReporter(@NotNull ErrorReporter errorReporter);
053
054 public abstract void setStorage(@NotNull DescriptorDeserializersStorage storage);
055
056 @Nullable
057 protected static MemberSignature getCallableSignature(
058 @NotNull ProtoBuf.Callable proto,
059 @NotNull NameResolver nameResolver,
060 @NotNull AnnotatedCallableKind kind
061 ) {
062 SignatureDeserializer deserializer = new SignatureDeserializer(nameResolver);
063 switch (kind) {
064 case FUNCTION:
065 if (proto.hasExtension(JavaProtoBuf.methodSignature)) {
066 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.methodSignature));
067 }
068 break;
069 case PROPERTY_GETTER:
070 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
071 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.propertySignature).getGetter());
072 }
073 break;
074 case PROPERTY_SETTER:
075 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
076 return deserializer.methodSignature(proto.getExtension(JavaProtoBuf.propertySignature).getSetter());
077 }
078 break;
079 case PROPERTY:
080 if (proto.hasExtension(JavaProtoBuf.propertySignature)) {
081 JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature);
082
083 if (propertySignature.hasField()) {
084 JavaProtoBuf.JavaFieldSignature field = propertySignature.getField();
085 String type = deserializer.typeDescriptor(field.getType());
086 Name name = nameResolver.getName(field.getName());
087 return MemberSignature.fromFieldNameAndDesc(name, type);
088 }
089 else if (propertySignature.hasSyntheticMethod()) {
090 return deserializer.methodSignature(propertySignature.getSyntheticMethod());
091 }
092 }
093 break;
094 }
095 return null;
096 }
097
098 @Nullable
099 protected KotlinJvmBinaryClass findClassWithAnnotationsAndInitializers(
100 @NotNull ClassOrPackageFragmentDescriptor container,
101 @NotNull ProtoBuf.Callable proto,
102 @NotNull NameResolver nameResolver,
103 @NotNull AnnotatedCallableKind kind
104 ) {
105 if (container instanceof PackageFragmentDescriptor) {
106 return getPackagePartClassFqNameSafe((PackageFragmentDescriptor) container, proto, nameResolver);
107 }
108 else if (isClassObject(container) && isStaticFieldInOuter(proto)) {
109 // Backing fields of properties of a class object are generated in the outer class
110 return findKotlinClassByDescriptor((ClassOrPackageFragmentDescriptor) container.getContainingDeclaration());
111 }
112 else if (isTrait(container) && kind == AnnotatedCallableKind.PROPERTY) {
113 PackageFragmentDescriptor containingPackage = DescriptorUtils.getParentOfType(container, PackageFragmentDescriptor.class);
114 assert containingPackage != null : "Trait must have a package fragment among his parents: " + container;
115
116 if (proto.hasExtension(JavaProtoBuf.implClassName)) {
117 Name tImplName = nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
118 return kotlinClassFinder.findKotlinClass(containingPackage.getFqName().child(tImplName));
119 }
120 return null;
121 }
122
123 return findKotlinClassByDescriptor(container);
124 }
125
126 @Nullable
127 private KotlinJvmBinaryClass getPackagePartClassFqNameSafe(
128 @NotNull PackageFragmentDescriptor container,
129 @NotNull ProtoBuf.Callable proto,
130 @NotNull NameResolver nameResolver
131 ) {
132 if (proto.hasExtension(JavaProtoBuf.implClassName)) {
133 return kotlinClassFinder.findKotlinClass(container.getFqName().child(getPackagePartClassName(proto, nameResolver)));
134 }
135 return null;
136 }
137
138 @NotNull
139 public static Name getPackagePartClassName(@NotNull DeserializedCallableMemberDescriptor deserializedCallableMember) {
140 return getPackagePartClassName(deserializedCallableMember.getProto(), deserializedCallableMember.getNameResolver());
141 }
142
143 @NotNull
144 private static Name getPackagePartClassName(@NotNull ProtoBuf.Callable proto, @NotNull NameResolver nameResolver) {
145 return nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName));
146 }
147
148 private static boolean isStaticFieldInOuter(@NotNull ProtoBuf.Callable proto) {
149 if (!proto.hasExtension(JavaProtoBuf.propertySignature)) return false;
150 JavaProtoBuf.JavaPropertySignature propertySignature = proto.getExtension(JavaProtoBuf.propertySignature);
151 return propertySignature.hasField() && propertySignature.getField().getIsStaticInOuter();
152 }
153
154 @Nullable
155 protected KotlinJvmBinaryClass findKotlinClassByDescriptor(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
156 if (descriptor instanceof ClassDescriptor) {
157 return kotlinClassFinder.findKotlinClass(kotlinFqNameToJavaFqName(naiveKotlinFqName((ClassDescriptor) descriptor)));
158 }
159 else if (descriptor instanceof PackageFragmentDescriptor) {
160 return kotlinClassFinder.findKotlinClass(
161 PackageClassUtils.getPackageClassFqName(((PackageFragmentDescriptor) descriptor).getFqName()));
162 }
163 else {
164 throw new IllegalStateException("Unrecognized descriptor: " + descriptor);
165 }
166 }
167 }