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.descriptors.*;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
025 import org.jetbrains.jet.lang.descriptors.impl.*;
026 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
027 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
028 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
029 import org.jetbrains.jet.lang.types.Variance;
030 import org.jetbrains.jet.storage.StorageManager;
031
032 import java.util.ArrayList;
033 import java.util.Collections;
034 import java.util.List;
035
036 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable;
037 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.TypeParameter;
038 import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
039 import static org.jetbrains.jet.descriptors.serialization.descriptors.Deserializers.AnnotatedCallableKind;
040
041 public class DescriptorDeserializer {
042
043 @NotNull
044 public static DescriptorDeserializer create(
045 @NotNull StorageManager storageManager,
046 @NotNull DeclarationDescriptor containingDeclaration,
047 @NotNull NameResolver nameResolver,
048 @NotNull DescriptorFinder descriptorFinder,
049 @NotNull Deserializers annotationDeserializer
050 ) {
051 return new DescriptorDeserializer(storageManager,
052 new TypeDeserializer(storageManager, null, nameResolver, descriptorFinder,
053 "Deserializer for " + containingDeclaration.getName(), NONE),
054 containingDeclaration, nameResolver, annotationDeserializer);
055 }
056
057 @NotNull
058 public static DescriptorDeserializer create(
059 @NotNull StorageManager storageManager,
060 @NotNull TypeDeserializer typeDeserializer,
061 @NotNull DeclarationDescriptor containingDeclaration,
062 @NotNull NameResolver nameResolver,
063 @NotNull Deserializers annotationDeserializer
064 ) {
065 return new DescriptorDeserializer(storageManager, typeDeserializer, containingDeclaration, nameResolver, annotationDeserializer);
066 }
067
068 private final DeclarationDescriptor containingDeclaration;
069 private final NameResolver nameResolver;
070 private final TypeDeserializer typeDeserializer;
071 private final Deserializers deserializers;
072
073 private final StorageManager storageManager;
074
075 private DescriptorDeserializer(
076 @NotNull StorageManager storageManager,
077 @NotNull TypeDeserializer typeDeserializer,
078 @NotNull DeclarationDescriptor containingDeclaration,
079 @NotNull NameResolver nameResolver,
080 @NotNull Deserializers deserializers
081 ) {
082 this.storageManager = storageManager;
083 this.typeDeserializer = typeDeserializer;
084 this.containingDeclaration = containingDeclaration;
085 this.nameResolver = nameResolver;
086 this.deserializers = deserializers;
087 }
088
089 @NotNull
090 public TypeDeserializer getTypeDeserializer() {
091 return typeDeserializer;
092 }
093
094 @NotNull
095 public NameResolver getNameResolver() {
096 return nameResolver;
097 }
098
099 @NotNull
100 public DescriptorDeserializer createChildDeserializer(
101 @NotNull DeclarationDescriptor descriptor,
102 @NotNull final List<TypeParameter> typeParameterProtos,
103 @NotNull final List<TypeParameterDescriptor> typeParameters
104 ) {
105 TypeDeserializer childTypeDeserializer = new TypeDeserializer(
106 storageManager,
107 typeDeserializer, "Child deserializer for " + descriptor.getName(),
108 new TypeDeserializer.TypeParameterResolver() {
109 @NotNull
110 @Override
111 public List<DeserializedTypeParameterDescriptor> getTypeParameters(@NotNull TypeDeserializer typeDeserializer) {
112 List<DeserializedTypeParameterDescriptor> descriptors = typeParameters(typeParameterProtos, typeDeserializer);
113 typeParameters.addAll(descriptors);
114 return descriptors;
115 }
116 });
117 return create(storageManager, childTypeDeserializer, descriptor, nameResolver, deserializers);
118 }
119
120 @NotNull
121 public CallableMemberDescriptor loadCallable(@NotNull Callable proto) {
122 Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(proto.getFlags());
123 switch (callableKind) {
124 case FUN:
125 return loadFunction(proto);
126 case VAL:
127 case VAR:
128 return loadProperty(proto);
129 case CONSTRUCTOR:
130 return loadConstructor(proto);
131 }
132 throw new IllegalArgumentException("Unsupported callable kind: " + callableKind);
133 }
134
135 @NotNull
136 private PropertyDescriptor loadProperty(@NotNull final Callable proto) {
137 final int flags = proto.getFlags();
138
139 PropertyDescriptorImpl property = new PropertyDescriptorImpl(
140 containingDeclaration,
141 getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
142 modality(Flags.MODALITY.get(flags)),
143 visibility(Flags.VISIBILITY.get(flags)),
144 Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
145 nameResolver.getName(proto.getName()),
146 memberKind(Flags.MEMBER_KIND.get(flags))
147 );
148
149 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
150 DescriptorDeserializer local = createChildDeserializer(property, proto.getTypeParameterList(), typeParameters);
151 property.setType(
152 local.typeDeserializer.type(proto.getReturnType()),
153 typeParameters,
154 getExpectedThisObject(),
155 local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
156 );
157
158 PropertyGetterDescriptorImpl getter = null;
159 PropertySetterDescriptorImpl setter = null;
160
161 if (Flags.HAS_GETTER.get(flags)) {
162 int getterFlags = proto.getGetterFlags();
163 boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
164 if (isNotDefault) {
165 getter = new PropertyGetterDescriptorImpl(
166 property, getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
167 modality(Flags.MODALITY.get(getterFlags)), visibility(Flags.VISIBILITY.get(getterFlags)),
168 isNotDefault, !isNotDefault, property.getKind()
169 );
170 }
171 else {
172 getter = DescriptorFactory.createDefaultGetter(property);
173 }
174 getter.initialize(property.getReturnType());
175 }
176
177 if (Flags.HAS_SETTER.get(flags)) {
178 int setterFlags = proto.getSetterFlags();
179 boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
180 if (isNotDefault) {
181 setter = new PropertySetterDescriptorImpl(
182 property, getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
183 modality(Flags.MODALITY.get(setterFlags)), visibility(Flags.VISIBILITY.get(setterFlags)),
184 isNotDefault, !isNotDefault, property.getKind()
185 );
186 DescriptorDeserializer setterLocal = local.createChildDeserializer(setter, Collections.<TypeParameter>emptyList(),
187 Collections.<TypeParameterDescriptor>emptyList());
188 List<ValueParameterDescriptor> valueParameters = setterLocal.valueParameters(proto, AnnotatedCallableKind.PROPERTY_SETTER);
189 assert valueParameters.size() == 1 : "Property setter should have a single value parameter: " + setter;
190 setter.initialize(valueParameters.get(0));
191 }
192 else {
193 setter = DescriptorFactory.createDefaultSetter(property);
194 }
195 }
196
197 if (Flags.HAS_CONSTANT.get(flags)) {
198 property.setCompileTimeInitializer(
199 storageManager.createNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
200 @Nullable
201 @Override
202 public CompileTimeConstant<?> invoke() {
203 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
204 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
205 return deserializers.getConstantDeserializer().loadPropertyConstant(
206 (ClassOrPackageFragmentDescriptor) containingDeclaration,
207 proto, nameResolver,
208 AnnotatedCallableKind.PROPERTY);
209 }
210 })
211 );
212 }
213
214 property.initialize(getter, setter);
215
216 return property;
217 }
218
219 @NotNull
220 private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
221 int flags = proto.getFlags();
222 DeserializedSimpleFunctionDescriptor function = new DeserializedSimpleFunctionDescriptor(
223 containingDeclaration, proto,
224 deserializers,
225 nameResolver
226 );
227 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
228 DescriptorDeserializer local = createChildDeserializer(function, proto.getTypeParameterList(), typeParameters);
229 function.initialize(
230 local.typeDeserializer.typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
231 getExpectedThisObject(),
232 typeParameters,
233 local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
234 local.typeDeserializer.type(proto.getReturnType()),
235 modality(Flags.MODALITY.get(flags)),
236 visibility(Flags.VISIBILITY.get(flags))
237 );
238 return function;
239 }
240
241 @Nullable
242 private ReceiverParameterDescriptor getExpectedThisObject() {
243 return containingDeclaration instanceof ClassDescriptor
244 ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
245 }
246
247 @NotNull
248 private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
249 ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
250 ConstructorDescriptorImpl descriptor = new ConstructorDescriptorImpl(
251 classDescriptor,
252 getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
253 // TODO: primary
254 true);
255 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
256 DescriptorDeserializer local = createChildDeserializer(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
257 descriptor.initialize(
258 classDescriptor.getTypeConstructor().getParameters(),
259 local.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
260 visibility(Flags.VISIBILITY.get(proto.getFlags())),
261 DescriptorUtils.isConstructorOfStaticNestedClass(descriptor)
262 );
263 descriptor.setReturnType(local.typeDeserializer.type(proto.getReturnType()));
264 return descriptor;
265 }
266
267 @NotNull
268 private Annotations getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
269 return getAnnotations(containingDeclaration, proto, flags, kind, deserializers.getAnnotationDeserializer(), nameResolver);
270 }
271
272 public static Annotations getAnnotations(
273 @NotNull DeclarationDescriptor containingDeclaration,
274 @NotNull Callable proto,
275 int flags,
276 @NotNull AnnotatedCallableKind kind,
277 @NotNull AnnotationDeserializer annotationDeserializer,
278 @NotNull NameResolver nameResolver
279 ) {
280 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
281 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
282 return Flags.HAS_ANNOTATIONS.get(flags)
283 ? annotationDeserializer
284 .loadCallableAnnotations((ClassOrPackageFragmentDescriptor) containingDeclaration, proto, nameResolver, kind)
285 : Annotations.EMPTY;
286 }
287
288 public static CallableMemberDescriptor.Kind memberKind(Callable.MemberKind memberKind) {
289 switch (memberKind) {
290 case DECLARATION:
291 return CallableMemberDescriptor.Kind.DECLARATION;
292 case FAKE_OVERRIDE:
293 return CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
294 case DELEGATION:
295 return CallableMemberDescriptor.Kind.DELEGATION;
296 case SYNTHESIZED:
297 return CallableMemberDescriptor.Kind.SYNTHESIZED;
298 }
299 throw new IllegalArgumentException("Unknown member kind: " + memberKind);
300 }
301
302 @NotNull
303 public static Modality modality(@NotNull ProtoBuf.Modality modality) {
304 switch (modality) {
305 case FINAL:
306 return Modality.FINAL;
307 case OPEN:
308 return Modality.OPEN;
309 case ABSTRACT:
310 return Modality.ABSTRACT;
311 }
312 throw new IllegalArgumentException("Unknown modality: " + modality);
313 }
314
315 @NotNull
316 public static Visibility visibility(@NotNull ProtoBuf.Visibility visibility) {
317 switch (visibility) {
318 case INTERNAL:
319 return Visibilities.INTERNAL;
320 case PRIVATE:
321 return Visibilities.PRIVATE;
322 case PROTECTED:
323 return Visibilities.PROTECTED;
324 case PUBLIC:
325 return Visibilities.PUBLIC;
326 case EXTRA:
327 throw new UnsupportedOperationException("Extra visibilities are not supported yet"); // TODO
328 }
329 throw new IllegalArgumentException("Unknown visibility: " + visibility);
330 }
331
332 @NotNull
333 public static ClassKind classKind(@NotNull ProtoBuf.Class.Kind kind) {
334 switch (kind) {
335 case CLASS:
336 return ClassKind.CLASS;
337 case TRAIT:
338 return ClassKind.TRAIT;
339 case ENUM_CLASS:
340 return ClassKind.ENUM_CLASS;
341 case ENUM_ENTRY:
342 return ClassKind.ENUM_ENTRY;
343 case ANNOTATION_CLASS:
344 return ClassKind.ANNOTATION_CLASS;
345 case OBJECT:
346 return ClassKind.OBJECT;
347 case CLASS_OBJECT:
348 return ClassKind.CLASS_OBJECT;
349 }
350 throw new IllegalArgumentException("Unknown class kind: " + kind);
351 }
352
353 @NotNull
354 public List<DeserializedTypeParameterDescriptor> typeParameters(
355 @NotNull List<TypeParameter> protos,
356 @NotNull TypeDeserializer typeDeserializer
357 ) {
358 List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
359 for (int i = 0; i < protos.size(); i++) {
360 TypeParameter proto = protos.get(i);
361 DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
362 storageManager,
363 typeDeserializer,
364 proto,
365 containingDeclaration,
366 nameResolver.getName(proto.getName()),
367 variance(proto.getVariance()),
368 proto.getReified(),
369 i
370 );
371 result.add(descriptor);
372 }
373 return result;
374 }
375
376 private static Variance variance(TypeParameter.Variance proto) {
377 switch (proto) {
378 case IN:
379 return Variance.IN_VARIANCE;
380 case OUT:
381 return Variance.OUT_VARIANCE;
382 case INV:
383 return Variance.INVARIANT;
384 }
385 throw new IllegalStateException("Unknown projection: " + proto);
386 }
387
388 @NotNull
389 private List<ValueParameterDescriptor> valueParameters(@NotNull Callable callable, @NotNull AnnotatedCallableKind kind) {
390 DeclarationDescriptor containerOfCallable = containingDeclaration.getContainingDeclaration();
391 assert containerOfCallable instanceof ClassOrPackageFragmentDescriptor
392 : "Only members in classes or package fragments should be serialized: " + containerOfCallable;
393 ClassOrPackageFragmentDescriptor classOrPackage = (ClassOrPackageFragmentDescriptor) containerOfCallable;
394
395 List<Callable.ValueParameter> protos = callable.getValueParameterList();
396 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
397 for (int i = 0; i < protos.size(); i++) {
398 Callable.ValueParameter proto = protos.get(i);
399 result.add(new ValueParameterDescriptorImpl(
400 containingDeclaration,
401 i,
402 getAnnotations(classOrPackage, callable, kind, proto),
403 nameResolver.getName(proto.getName()),
404 typeDeserializer.type(proto.getType()),
405 Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
406 typeDeserializer.typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null))
407 );
408 }
409 return result;
410 }
411
412 @NotNull
413 private Annotations getAnnotations(
414 @NotNull ClassOrPackageFragmentDescriptor classOrPackage,
415 @NotNull Callable callable,
416 @NotNull AnnotatedCallableKind kind,
417 @NotNull Callable.ValueParameter valueParameter
418 ) {
419 return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags())
420 ? deserializers.getAnnotationDeserializer().loadValueParameterAnnotations(classOrPackage, callable, nameResolver, kind, valueParameter)
421 : Annotations.EMPTY;
422 }
423 }