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