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