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.descriptors;
018
019 import jet.Function0;
020 import jet.Function1;
021 import kotlin.KotlinPackage;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.descriptors.serialization.*;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
027 import org.jetbrains.jet.lang.descriptors.impl.AbstractClassDescriptor;
028 import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
029 import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor;
030 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
031 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
032 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
033 import org.jetbrains.jet.lang.resolve.OverridingUtil;
034 import org.jetbrains.jet.lang.resolve.name.Name;
035 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
036 import org.jetbrains.jet.lang.types.ErrorUtils;
037 import org.jetbrains.jet.lang.types.JetType;
038 import org.jetbrains.jet.lang.types.TypeConstructor;
039 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
040 import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
041 import org.jetbrains.jet.storage.NotNullLazyValue;
042 import org.jetbrains.jet.storage.NullableLazyValue;
043 import org.jetbrains.jet.storage.StorageManager;
044
045 import java.util.*;
046
047 import static org.jetbrains.jet.descriptors.serialization.TypeDeserializer.TypeParameterResolver.NONE;
048 import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
049
050 public class DeserializedClassDescriptor extends AbstractClassDescriptor implements ClassDescriptor {
051
052 private final ClassId classId;
053 private final ProtoBuf.Class classProto;
054 private final StorageManager storageManager;
055 private final TypeDeserializer typeDeserializer;
056 private final DescriptorDeserializer deserializer;
057 private final DeserializedMemberScope memberScope;
058
059 private final NullableLazyValue<ConstructorDescriptor> primaryConstructor;
060
061 private final AnnotationDeserializer annotationDeserializer;
062 private final NotNullLazyValue<List<AnnotationDescriptor>> annotations;
063
064 private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
065
066 private final NestedClassDescriptors nestedClasses;
067
068 private final NotNullLazyValue<DeclarationDescriptor> containingDeclaration;
069 private final DeserializedClassTypeConstructor typeConstructor;
070 private final Modality modality;
071 private final Visibility visibility;
072 private final ClassKind kind;
073 private final boolean isInner;
074 private final DescriptorFinder descriptorFinder;
075
076 public DeserializedClassDescriptor(
077 @NotNull StorageManager storageManager,
078 @NotNull AnnotationDeserializer annotationResolver,
079 @NotNull DescriptorFinder descriptorFinder,
080 @NotNull NameResolver nameResolver,
081 @NotNull ProtoBuf.Class classProto
082 ) {
083 super(storageManager, nameResolver.getClassId(classProto.getFqName()).getRelativeClassName().shortName());
084 this.classProto = classProto;
085 this.classId = nameResolver.getClassId(classProto.getFqName());
086 this.storageManager = storageManager;
087 this.descriptorFinder = descriptorFinder;
088
089 TypeDeserializer notNullTypeDeserializer = new TypeDeserializer(storageManager, null, nameResolver,
090 descriptorFinder, "Deserializer for class " + getName(), NONE);
091 DescriptorDeserializer outerDeserializer = DescriptorDeserializer.create(storageManager, notNullTypeDeserializer,
092 this, nameResolver, annotationResolver);
093 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(classProto.getTypeParameterCount());
094 this.deserializer = outerDeserializer.createChildDeserializer(this, classProto.getTypeParameterList(), typeParameters);
095 this.typeDeserializer = deserializer.getTypeDeserializer();
096
097 this.containingDeclaration = storageManager.createLazyValue(new Function0<DeclarationDescriptor>() {
098 @Override
099 public DeclarationDescriptor invoke() {
100 return computeContainingDeclaration();
101 }
102 });
103
104 this.typeConstructor = new DeserializedClassTypeConstructor(typeParameters);
105 this.memberScope = new DeserializedClassMemberScope(storageManager, this);
106
107 int flags = classProto.getFlags();
108 this.modality = DescriptorDeserializer.modality(Flags.MODALITY.get(flags));
109 this.visibility = DescriptorDeserializer.visibility(Flags.VISIBILITY.get(flags));
110 this.kind = DescriptorDeserializer.classKind(Flags.CLASS_KIND.get(flags));
111 this.isInner = Flags.INNER.get(flags);
112
113 this.annotationDeserializer = annotationResolver;
114 this.annotations = storageManager.createLazyValue(new Function0<List<AnnotationDescriptor>>() {
115 @Override
116 public List<AnnotationDescriptor> invoke() {
117 return computeAnnotations();
118 }
119 });
120
121 this.primaryConstructor = storageManager.createNullableLazyValue(new Function0<ConstructorDescriptor>() {
122 @Override
123 public ConstructorDescriptor invoke() {
124 return computePrimaryConstructor();
125 }
126 });
127
128 this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptor>() {
129 @Override
130 public ClassDescriptor invoke() {
131 return computeClassObjectDescriptor();
132 }
133 });
134
135 this.nestedClasses = new NestedClassDescriptors();
136 }
137
138 @NotNull
139 @Override
140 public DeclarationDescriptor getContainingDeclaration() {
141 return containingDeclaration.invoke();
142 }
143
144 @NotNull
145 private DeclarationDescriptor computeContainingDeclaration() {
146 ClassOrNamespaceDescriptor result = classId.isTopLevelClass() ?
147 descriptorFinder.findPackage(classId.getPackageFqName()) :
148 descriptorFinder.findClass(classId.getOuterClassId());
149 return result != null ? result : ErrorUtils.getErrorModule();
150 }
151
152 @NotNull
153 @Override
154 public TypeConstructor getTypeConstructor() {
155 return typeConstructor;
156 }
157
158
159 @NotNull
160 @Override
161 public ClassKind getKind() {
162 return kind;
163 }
164
165 @NotNull
166 @Override
167 public Modality getModality() {
168 return modality;
169 }
170
171 @NotNull
172 @Override
173 public Visibility getVisibility() {
174 return visibility;
175 }
176
177 @Override
178 public boolean isInner() {
179 return isInner;
180 }
181
182 private List<AnnotationDescriptor> computeAnnotations() {
183 if (!Flags.HAS_ANNOTATIONS.get(classProto.getFlags())) {
184 return Collections.emptyList();
185 }
186 return annotationDeserializer.loadClassAnnotations(this, classProto);
187 }
188
189 @NotNull
190 @Override
191 public List<AnnotationDescriptor> getAnnotations() {
192 return annotations.invoke();
193 }
194
195 @NotNull
196 @Override
197 protected JetScope getScopeForMemberLookup() {
198 return memberScope;
199 }
200
201 @Nullable
202 private ConstructorDescriptor computePrimaryConstructor() {
203 if (!classProto.hasPrimaryConstructor()) return null;
204
205 ProtoBuf.Class.PrimaryConstructor constructorProto = classProto.getPrimaryConstructor();
206 if (!constructorProto.hasData()) {
207 ConstructorDescriptorImpl descriptor = DescriptorFactory.createPrimaryConstructorForObject(this);
208 descriptor.setReturnType(getDefaultType());
209 return descriptor;
210 }
211
212 return (ConstructorDescriptor) deserializer.loadCallable(constructorProto.getData());
213 }
214
215 @Nullable
216 @Override
217 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
218 return primaryConstructor.invoke();
219 }
220
221 @NotNull
222 @Override
223 public Collection<ConstructorDescriptor> getConstructors() {
224 ConstructorDescriptor constructor = getUnsubstitutedPrimaryConstructor();
225 if (constructor == null) {
226 return Collections.emptyList();
227 }
228 // TODO: other constructors
229 return Collections.singletonList(constructor);
230 }
231
232 @Nullable
233 private ClassDescriptor computeClassObjectDescriptor() {
234 if (!classProto.hasClassObject()) {
235 return null;
236 }
237
238 if (getKind() == ClassKind.ENUM_CLASS) {
239 return createEnumClassObject();
240 }
241
242 if (getKind() == ClassKind.OBJECT) {
243 ProtoBuf.Class.ClassObject classObjectProto = classProto.getClassObject();
244 if (!classObjectProto.hasData()) {
245 throw new IllegalStateException("Object should have a serialized class object: " + classId);
246 }
247
248 return new DeserializedClassDescriptor(storageManager, annotationDeserializer, descriptorFinder, deserializer.getNameResolver(),
249 classObjectProto.getData());
250 }
251
252 return descriptorFinder.findClass(classId.createNestedClassId(getClassObjectName(getName())));
253 }
254
255 @NotNull
256 private MutableClassDescriptor createEnumClassObject() {
257 MutableClassDescriptor classObject = new MutableClassDescriptor(this, getScopeForMemberLookup(), ClassKind.CLASS_OBJECT,
258 false, getClassObjectName(getName()));
259 classObject.setModality(Modality.FINAL);
260 classObject.setVisibility(DescriptorUtils.getSyntheticClassObjectVisibility());
261 classObject.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
262 classObject.setPrimaryConstructor(DescriptorFactory.createPrimaryConstructorForObject(classObject));
263 classObject.createTypeConstructor();
264
265 JetType enumType = getDefaultType();
266 JetType enumArrayType = KotlinBuiltIns.getInstance().getArrayType(enumType);
267 classObject.getBuilder().addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValuesMethod(classObject, enumArrayType));
268 classObject.getBuilder().addFunctionDescriptor(DescriptorFactory.createEnumClassObjectValueOfMethod(classObject, enumType));
269
270 return classObject;
271 }
272
273 @Nullable
274 @Override
275 public ClassDescriptor getClassObjectDescriptor() {
276 return classObjectDescriptor.invoke();
277 }
278
279 private Collection<JetType> computeSuperTypes() {
280 List<JetType> supertypes = new ArrayList<JetType>(classProto.getSupertypeCount());
281 for (ProtoBuf.Type supertype : classProto.getSupertypeList()) {
282 supertypes.add(typeDeserializer.type(supertype));
283 }
284 return supertypes;
285 }
286
287 @Override
288 public String toString() {
289 return "deserialized class " + getName().toString();
290 }
291
292 private class DeserializedClassTypeConstructor implements TypeConstructor {
293 private final Collection<JetType> supertypes = computeSuperTypes();
294 private final List<TypeParameterDescriptor> parameters;
295
296 public DeserializedClassTypeConstructor(@NotNull List<TypeParameterDescriptor> typeParameters) {
297 parameters = typeParameters;
298 }
299
300 @NotNull
301 @Override
302 public List<TypeParameterDescriptor> getParameters() {
303 return parameters;
304 }
305
306 @NotNull
307 @Override
308 public Collection<JetType> getSupertypes() {
309 return supertypes;
310 }
311
312 @Override
313 public boolean isFinal() {
314 return !getModality().isOverridable();
315 }
316
317 @Override
318 public boolean isDenotable() {
319 return true;
320 }
321
322 @Nullable
323 @Override
324 public ClassifierDescriptor getDeclarationDescriptor() {
325 return DeserializedClassDescriptor.this;
326 }
327
328 @NotNull
329 @Override
330 public List<AnnotationDescriptor> getAnnotations() {
331 return Collections.emptyList(); // TODO
332 }
333
334 @Override
335 public String toString() {
336 return getName().toString();
337 }
338 }
339
340 private static class DeserializedClassMemberScope extends DeserializedMemberScope {
341 private final DeserializedClassDescriptor classDescriptor;
342
343 public DeserializedClassMemberScope(@NotNull StorageManager storageManager, @NotNull DeserializedClassDescriptor classDescriptor) {
344 super(storageManager, classDescriptor, classDescriptor.deserializer, classDescriptor.classProto.getMemberList());
345 this.classDescriptor = classDescriptor;
346 }
347
348 @Override
349 protected void computeNonDeclaredFunctions(
350 @NotNull Name name, @NotNull Collection<FunctionDescriptor> functions
351 ) {
352 Collection<FunctionDescriptor> fromSupertypes = new ArrayList<FunctionDescriptor>();
353 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
354 fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
355 }
356 generateFakeOverrides(name, fromSupertypes, functions);
357 }
358
359 @Override
360 protected void computeNonDeclaredProperties(
361 @NotNull Name name, @NotNull Collection<PropertyDescriptor> property
362 ) {
363 Collection<PropertyDescriptor> fromSupertypes = new ArrayList<PropertyDescriptor>();
364 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
365 //noinspection unchecked
366 fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
367 }
368 generateFakeOverrides(name, fromSupertypes, property);
369 }
370
371 private <D extends CallableMemberDescriptor> void generateFakeOverrides(
372 @NotNull Name name,
373 @NotNull Collection<D> fromSupertypes,
374 @NotNull final Collection<D> result
375 ) {
376 List<CallableMemberDescriptor> fromCurrent = new ArrayList<CallableMemberDescriptor>(result);
377 OverridingUtil.generateOverridesInFunctionGroup(
378 name,
379 fromSupertypes,
380 fromCurrent,
381 classDescriptor,
382 new OverridingUtil.DescriptorSink() {
383 @Override
384 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
385 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new OverridingUtil.NotInferredVisibilitySink() {
386 @Override
387 public void cannotInferVisibility(@NotNull CallableMemberDescriptor descriptor) {
388 // Do nothing
389 // TODO: do something
390 }
391 });
392 //noinspection unchecked
393 result.add((D) fakeOverride);
394 }
395
396 @Override
397 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
398 // TODO report conflicts
399 }
400 }
401 );
402 }
403
404 @Override
405 protected void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
406 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
407 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
408 if (descriptor instanceof FunctionDescriptor) {
409 result.addAll(getFunctions(descriptor.getName()));
410 }
411 else if (descriptor instanceof PropertyDescriptor) {
412 result.addAll(getProperties(descriptor.getName()));
413 }
414 // Nothing else is inherited
415 }
416 }
417 }
418
419 @Nullable
420 @Override
421 protected ReceiverParameterDescriptor getImplicitReceiver() {
422 return classDescriptor.getThisAsReceiverParameter();
423 }
424
425 @Nullable
426 @Override
427 protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
428 return classDescriptor.nestedClasses.findClass.invoke(name);
429 }
430
431 @Override
432 protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
433 result.addAll(classDescriptor.nestedClasses.getAllDescriptors());
434 }
435 }
436
437 private class NestedClassDescriptors {
438 private final Set<Name> nestedClassNames;
439 private final MemoizedFunctionToNullable<Name, ClassDescriptor> findClass;
440 private final Set<Name> enumEntryNames;
441
442 public NestedClassDescriptors() {
443 this.nestedClassNames = nestedClassNames();
444 this.enumEntryNames = enumEntryNames();
445
446 final NotNullLazyValue<Collection<Name>> enumMemberNames = storageManager.createLazyValue(new Function0<Collection<Name>>() {
447 @Override
448 public Collection<Name> invoke() {
449 return computeEnumMemberNames();
450 }
451 });
452
453 this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1<Name, ClassDescriptor>() {
454 @Override
455 public ClassDescriptor invoke(Name name) {
456 if (enumEntryNames.contains(name)) {
457 return EnumEntrySyntheticClassDescriptor
458 .create(storageManager, DeserializedClassDescriptor.this, name, enumMemberNames);
459 }
460 if (nestedClassNames.contains(name)) {
461 return descriptorFinder.findClass(classId.createNestedClassId(name));
462 }
463 return null;
464 }
465 });
466 }
467
468 @NotNull
469 private Set<Name> nestedClassNames() {
470 Set<Name> result = new HashSet<Name>();
471 NameResolver nameResolver = deserializer.getNameResolver();
472 for (Integer index : classProto.getNestedClassNameList()) {
473 result.add(nameResolver.getName(index));
474 }
475 return result;
476 }
477
478 @NotNull
479 private Set<Name> enumEntryNames() {
480 if (getKind() != ClassKind.ENUM_CLASS) {
481 return Collections.emptySet();
482 }
483
484 Set<Name> result = new HashSet<Name>();
485 NameResolver nameResolver = deserializer.getNameResolver();
486 for (Integer index : classProto.getEnumEntryList()) {
487 result.add(nameResolver.getName(index));
488 }
489 return result;
490 }
491
492 @NotNull
493 private Collection<Name> computeEnumMemberNames() {
494 Collection<Name> result = new HashSet<Name>();
495
496 for (JetType supertype : getTypeConstructor().getSupertypes()) {
497 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
498 if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof PropertyDescriptor) {
499 result.add(descriptor.getName());
500 }
501 }
502 }
503
504 final NameResolver nameResolver = deserializer.getNameResolver();
505 return KotlinPackage.mapTo(classProto.getMemberList(), result, new Function1<ProtoBuf.Callable, Name>() {
506 @Override
507 public Name invoke(@NotNull ProtoBuf.Callable callable) {
508 return nameResolver.getName(callable.getName());
509 }
510 });
511 }
512
513 @NotNull
514 public Collection<ClassDescriptor> getAllDescriptors() {
515 Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(nestedClassNames.size() + enumEntryNames.size());
516 for (Name name : nestedClassNames) {
517 ClassDescriptor descriptor = findClass.invoke(name);
518 if (descriptor != null) {
519 result.add(descriptor);
520 }
521 }
522 for (Name name : enumEntryNames) {
523 ClassDescriptor descriptor = findClass.invoke(name);
524 if (descriptor != null) {
525 result.add(descriptor);
526 }
527 }
528 return result;
529 }
530 }
531 }
532