001 /*
002 * Copyright 2010-2013 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.descriptors.serialization;
018
019 import kotlin.Function0;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.descriptors.serialization.context.DeserializationContextWithTypes;
023 import org.jetbrains.jet.descriptors.serialization.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.*;
025 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
026 import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
027 import org.jetbrains.jet.lang.descriptors.impl.PropertyGetterDescriptorImpl;
028 import org.jetbrains.jet.lang.descriptors.impl.PropertySetterDescriptorImpl;
029 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
030 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
031 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
032
033 import java.util.ArrayList;
034 import java.util.Collections;
035 import java.util.List;
036
037 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable;
038 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.TypeParameter;
039 import static org.jetbrains.jet.descriptors.serialization.SerializationPackage.*;
040
041 public class MemberDeserializer {
042
043 private final DeserializationContextWithTypes context;
044
045 public MemberDeserializer(@NotNull DeserializationContextWithTypes context) {
046 this.context = context;
047 }
048
049 @NotNull
050 public CallableMemberDescriptor loadCallable(@NotNull Callable proto) {
051 Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(proto.getFlags());
052 switch (callableKind) {
053 case FUN:
054 return loadFunction(proto);
055 case VAL:
056 case VAR:
057 return loadProperty(proto);
058 case CONSTRUCTOR:
059 return loadConstructor(proto);
060 }
061 throw new IllegalArgumentException("Unsupported callable kind: " + callableKind);
062 }
063
064 @NotNull
065 private PropertyDescriptor loadProperty(@NotNull final Callable proto) {
066 final int flags = proto.getFlags();
067
068 DeserializedPropertyDescriptor property = new DeserializedPropertyDescriptor(
069 context.getContainingDeclaration(),
070 null,
071 getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
072 modality(Flags.MODALITY.get(flags)),
073 visibility(Flags.VISIBILITY.get(flags)),
074 Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
075 context.getNameResolver().getName(proto.getName()),
076 SerializationPackage.memberKind(Flags.MEMBER_KIND.get(flags)),
077 proto,
078 context.getNameResolver()
079 );
080
081 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
082 DeserializationContextWithTypes local = context.childContext(property, proto.getTypeParameterList(), typeParameters);
083 property.setType(
084 local.getTypeDeserializer().type(proto.getReturnType()),
085 typeParameters,
086 getExpectedThisObject(),
087 local.getTypeDeserializer().typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
088 );
089
090 PropertyGetterDescriptorImpl getter = null;
091 PropertySetterDescriptorImpl setter = null;
092
093 if (Flags.HAS_GETTER.get(flags)) {
094 int getterFlags = proto.getGetterFlags();
095 boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
096 if (isNotDefault) {
097 getter = new PropertyGetterDescriptorImpl(property,
098 getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
099 modality(Flags.MODALITY.get(getterFlags)),
100 visibility(Flags.VISIBILITY.get(getterFlags)),
101 isNotDefault, !isNotDefault,
102 property.getKind(), null, SourceElement.NO_SOURCE);
103 }
104 else {
105 getter = DescriptorFactory.createDefaultGetter(property);
106 }
107 getter.initialize(property.getReturnType());
108 }
109
110 if (Flags.HAS_SETTER.get(flags)) {
111 int setterFlags = proto.getSetterFlags();
112 boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
113 if (isNotDefault) {
114 setter = new PropertySetterDescriptorImpl(property,
115 getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
116 modality(Flags.MODALITY.get(setterFlags)),
117 visibility(Flags.VISIBILITY.get(setterFlags)), isNotDefault,
118 !isNotDefault,
119 property.getKind(), null, SourceElement.NO_SOURCE);
120 DeserializationContextWithTypes setterLocal = local.childContext(setter, Collections.<TypeParameter>emptyList(),
121 Collections.<TypeParameterDescriptor>emptyList());
122 List<ValueParameterDescriptor> valueParameters
123 = setterLocal.getDeserializer().valueParameters(proto, AnnotatedCallableKind.PROPERTY_SETTER);
124 assert valueParameters.size() == 1 : "Property setter should have a single value parameter: " + setter;
125 setter.initialize(valueParameters.get(0));
126 }
127 else {
128 setter = DescriptorFactory.createDefaultSetter(property);
129 }
130 }
131
132 if (Flags.HAS_CONSTANT.get(flags)) {
133 property.setCompileTimeInitializer(
134 context.getStorageManager().createNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
135 @Nullable
136 @Override
137 public CompileTimeConstant<?> invoke() {
138 DeclarationDescriptor containingDeclaration = context.getContainingDeclaration();
139 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
140 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
141 return context.getConstantLoader().loadPropertyConstant(
142 (ClassOrPackageFragmentDescriptor) containingDeclaration, proto,
143 context.getNameResolver(), AnnotatedCallableKind.PROPERTY);
144 }
145 })
146 );
147 }
148
149 property.initialize(getter, setter);
150
151 return property;
152 }
153
154 @NotNull
155 private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
156 int flags = proto.getFlags();
157 DeserializedSimpleFunctionDescriptor function = DeserializedSimpleFunctionDescriptor.create(
158 context.getContainingDeclaration(), proto, context.getAnnotationLoader(), context.getNameResolver()
159 );
160 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
161 DeserializationContextWithTypes local = context.childContext(function, proto.getTypeParameterList(), typeParameters);
162 function.initialize(
163 local.getTypeDeserializer().typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
164 getExpectedThisObject(),
165 typeParameters,
166 local.getDeserializer().valueParameters(proto, AnnotatedCallableKind.FUNCTION),
167 local.getTypeDeserializer().type(proto.getReturnType()),
168 modality(Flags.MODALITY.get(flags)),
169 visibility(Flags.VISIBILITY.get(flags))
170 );
171 return function;
172 }
173
174 @Nullable
175 private ReceiverParameterDescriptor getExpectedThisObject() {
176 DeclarationDescriptor containingDeclaration = context.getContainingDeclaration();
177 return containingDeclaration instanceof ClassDescriptor
178 ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
179 }
180
181 @NotNull
182 private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
183 ClassDescriptor classDescriptor = (ClassDescriptor) context.getContainingDeclaration();
184 ConstructorDescriptorImpl descriptor = ConstructorDescriptorImpl.create(
185 classDescriptor,
186 getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
187 // TODO: primary
188 true, SourceElement.NO_SOURCE);
189 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
190 DeserializationContextWithTypes local = context.childContext(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
191 descriptor.initialize(
192 classDescriptor.getTypeConstructor().getParameters(),
193 local.getDeserializer().valueParameters(proto, AnnotatedCallableKind.FUNCTION),
194 visibility(Flags.VISIBILITY.get(proto.getFlags()))
195 );
196 descriptor.setReturnType(local.getTypeDeserializer().type(proto.getReturnType()));
197 return descriptor;
198 }
199
200 @NotNull
201 private Annotations getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
202 return getAnnotations(context.getContainingDeclaration(), proto, flags, kind, context.getAnnotationLoader(), context.getNameResolver());
203 }
204
205 public static Annotations getAnnotations(
206 @NotNull DeclarationDescriptor containingDeclaration,
207 @NotNull Callable proto,
208 int flags,
209 @NotNull AnnotatedCallableKind kind,
210 @NotNull AnnotationLoader annotationLoader,
211 @NotNull NameResolver nameResolver
212 ) {
213 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
214 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
215 return Flags.HAS_ANNOTATIONS.get(flags) ? annotationLoader.loadCallableAnnotations(
216 (ClassOrPackageFragmentDescriptor) containingDeclaration, proto, nameResolver, kind) : Annotations.EMPTY;
217 }
218
219 @NotNull
220 public List<DeserializedTypeParameterDescriptor> typeParameters(
221 @NotNull List<TypeParameter> protos,
222 @NotNull TypeDeserializer typeDeserializer
223 ) {
224 List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
225 for (int i = 0; i < protos.size(); i++) {
226 TypeParameter proto = protos.get(i);
227 DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
228 context.getStorageManager(),
229 typeDeserializer,
230 proto,
231 context.getContainingDeclaration(),
232 context.getNameResolver().getName(proto.getName()),
233 variance(proto.getVariance()),
234 proto.getReified(),
235 i
236 );
237 result.add(descriptor);
238 }
239 return result;
240 }
241
242 @NotNull
243 private List<ValueParameterDescriptor> valueParameters(@NotNull Callable callable, @NotNull AnnotatedCallableKind kind) {
244 DeclarationDescriptor containerOfCallable = context.getContainingDeclaration().getContainingDeclaration();
245 assert containerOfCallable instanceof ClassOrPackageFragmentDescriptor
246 : "Only members in classes or package fragments should be serialized: " + containerOfCallable;
247 ClassOrPackageFragmentDescriptor classOrPackage = (ClassOrPackageFragmentDescriptor) containerOfCallable;
248
249 List<Callable.ValueParameter> protos = callable.getValueParameterList();
250 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
251 for (int i = 0; i < protos.size(); i++) {
252 Callable.ValueParameter proto = protos.get(i);
253 result.add(new ValueParameterDescriptorImpl(
254 context.getContainingDeclaration(),
255 null,
256 i,
257 getAnnotations(classOrPackage, callable, kind, proto),
258 context.getNameResolver().getName(proto.getName()),
259 context.getTypeDeserializer().type(proto.getType()),
260 Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
261 context.getTypeDeserializer().typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null),
262 SourceElement.NO_SOURCE)
263 );
264 }
265 return result;
266 }
267
268 @NotNull
269 private Annotations getAnnotations(
270 @NotNull ClassOrPackageFragmentDescriptor classOrPackage,
271 @NotNull Callable callable,
272 @NotNull AnnotatedCallableKind kind,
273 @NotNull Callable.ValueParameter valueParameter
274 ) {
275 return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags()) ? context.getAnnotationLoader()
276 .loadValueParameterAnnotations(classOrPackage, callable, context.getNameResolver(), kind, valueParameter)
277 : Annotations.EMPTY;
278 }
279 }