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