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 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.Annotations;
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.AbstractClassTypeConstructor;
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, null);
285 classObject.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
286 }
287
288 @Override
289 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
290 throw new IllegalStateException("Conflict on enum class object override: " + fromSuper + " vs " + fromCurrent);
291 }
292 };
293
294 JetScope superScope = supertype.getMemberScope();
295
296 for (DeclarationDescriptor descriptor : superScope.getAllDescriptors()) {
297 if (descriptor instanceof FunctionDescriptor) {
298 Name name = descriptor.getName();
299 OverridingUtil.generateOverridesInFunctionGroup(name, superScope.getFunctions(name),
300 Collections.<FunctionDescriptor>emptySet(), classObject, sink);
301 }
302 }
303
304 return classObject;
305 }
306
307 @Nullable
308 @Override
309 public ClassDescriptor getClassObjectDescriptor() {
310 return classObjectDescriptor.invoke();
311 }
312
313 private Collection<JetType> computeSuperTypes() {
314 List<JetType> supertypes = new ArrayList<JetType>(classProto.getSupertypeCount());
315 for (ProtoBuf.Type supertype : classProto.getSupertypeList()) {
316 supertypes.add(typeDeserializer.type(supertype));
317 }
318 return supertypes;
319 }
320
321 @Override
322 public String toString() {
323 // not using descriptor render to preserve laziness
324 return "deserialized class " + getName().toString();
325 }
326
327 private class DeserializedClassTypeConstructor extends AbstractClassTypeConstructor {
328 private final Collection<JetType> supertypes = computeSuperTypes();
329 private final List<TypeParameterDescriptor> parameters;
330
331 public DeserializedClassTypeConstructor(@NotNull List<TypeParameterDescriptor> typeParameters) {
332 parameters = typeParameters;
333 }
334
335 @NotNull
336 @Override
337 public List<TypeParameterDescriptor> getParameters() {
338 return parameters;
339 }
340
341 @NotNull
342 @Override
343 public Collection<JetType> getSupertypes() {
344 // We cannot have error supertypes because subclasses inherit error functions from them
345 // Filtering right away means copying the list every time, so we check for the rare condition first, and only then filter
346 for (JetType supertype : supertypes) {
347 if (supertype.isError()) {
348 return KotlinPackage.filter(supertypes, new Function1<JetType, Boolean>() {
349 @Override
350 public Boolean invoke(JetType type) {
351 return !type.isError();
352 }
353 });
354 }
355 }
356 return supertypes;
357 }
358
359 @Override
360 public boolean isFinal() {
361 return !getModality().isOverridable();
362 }
363
364 @Override
365 public boolean isDenotable() {
366 return true;
367 }
368
369 @Nullable
370 @Override
371 public ClassifierDescriptor getDeclarationDescriptor() {
372 return DeserializedClassDescriptor.this;
373 }
374
375 @NotNull
376 @Override
377 public Annotations getAnnotations() {
378 return Annotations.EMPTY; // TODO
379 }
380
381 @Override
382 public String toString() {
383 return getName().toString();
384 }
385 }
386
387 private static class DeserializedClassMemberScope extends DeserializedMemberScope {
388 private final DeserializedClassDescriptor classDescriptor;
389
390 public DeserializedClassMemberScope(@NotNull StorageManager storageManager, @NotNull DeserializedClassDescriptor classDescriptor) {
391 super(storageManager, classDescriptor, classDescriptor.deserializer, classDescriptor.classProto.getMemberList());
392 this.classDescriptor = classDescriptor;
393 }
394
395 @Override
396 protected void computeNonDeclaredFunctions(
397 @NotNull Name name, @NotNull Collection<FunctionDescriptor> functions
398 ) {
399 Collection<FunctionDescriptor> fromSupertypes = new ArrayList<FunctionDescriptor>();
400 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
401 fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
402 }
403 generateFakeOverrides(name, fromSupertypes, functions);
404 }
405
406 @Override
407 protected void computeNonDeclaredProperties(
408 @NotNull Name name, @NotNull Collection<PropertyDescriptor> property
409 ) {
410 Collection<PropertyDescriptor> fromSupertypes = new ArrayList<PropertyDescriptor>();
411 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
412 //noinspection unchecked
413 fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
414 }
415 generateFakeOverrides(name, fromSupertypes, property);
416 }
417
418 private <D extends CallableMemberDescriptor> void generateFakeOverrides(
419 @NotNull Name name,
420 @NotNull Collection<D> fromSupertypes,
421 @NotNull final Collection<D> result
422 ) {
423 List<CallableMemberDescriptor> fromCurrent = new ArrayList<CallableMemberDescriptor>(result);
424 OverridingUtil.generateOverridesInFunctionGroup(
425 name,
426 fromSupertypes,
427 fromCurrent,
428 classDescriptor,
429 new OverridingUtil.DescriptorSink() {
430 @Override
431 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
432 // TODO: report "cannot infer visibility"
433 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null);
434 //noinspection unchecked
435 result.add((D) fakeOverride);
436 }
437
438 @Override
439 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
440 // TODO report conflicts
441 }
442 }
443 );
444 }
445
446 @Override
447 protected void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
448 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
449 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
450 if (descriptor instanceof FunctionDescriptor) {
451 result.addAll(getFunctions(descriptor.getName()));
452 }
453 else if (descriptor instanceof PropertyDescriptor) {
454 result.addAll(getProperties(descriptor.getName()));
455 }
456 // Nothing else is inherited
457 }
458 }
459 }
460
461 @Nullable
462 @Override
463 protected ReceiverParameterDescriptor getImplicitReceiver() {
464 return classDescriptor.getThisAsReceiverParameter();
465 }
466
467 @Nullable
468 @Override
469 protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
470 return classDescriptor.nestedClasses.findClass.invoke(name);
471 }
472
473 @Override
474 protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
475 result.addAll(classDescriptor.nestedClasses.getAllDescriptors());
476 }
477 }
478
479 private class NestedClassDescriptors {
480 private final Set<Name> nestedClassNames;
481 private final MemoizedFunctionToNullable<Name, ClassDescriptor> findClass;
482 private final Set<Name> enumEntryNames;
483
484 public NestedClassDescriptors() {
485 this.nestedClassNames = nestedClassNames();
486 this.enumEntryNames = enumEntryNames();
487
488 final NotNullLazyValue<Collection<Name>> enumMemberNames = storageManager.createLazyValue(new Function0<Collection<Name>>() {
489 @Override
490 public Collection<Name> invoke() {
491 return computeEnumMemberNames();
492 }
493 });
494
495 this.findClass = storageManager.createMemoizedFunctionWithNullableValues(new Function1<Name, ClassDescriptor>() {
496 @Override
497 public ClassDescriptor invoke(Name name) {
498 if (enumEntryNames.contains(name)) {
499 return EnumEntrySyntheticClassDescriptor
500 .create(storageManager, DeserializedClassDescriptor.this, name, enumMemberNames);
501 }
502 if (nestedClassNames.contains(name)) {
503 return descriptorFinder.findClass(classId.createNestedClassId(name));
504 }
505 return null;
506 }
507 });
508 }
509
510 @NotNull
511 private Set<Name> nestedClassNames() {
512 Set<Name> result = new HashSet<Name>();
513 NameResolver nameResolver = deserializer.getNameResolver();
514 for (Integer index : classProto.getNestedClassNameList()) {
515 result.add(nameResolver.getName(index));
516 }
517 return result;
518 }
519
520 @NotNull
521 private Set<Name> enumEntryNames() {
522 if (getKind() != ClassKind.ENUM_CLASS) {
523 return Collections.emptySet();
524 }
525
526 Set<Name> result = new HashSet<Name>();
527 NameResolver nameResolver = deserializer.getNameResolver();
528 for (Integer index : classProto.getEnumEntryList()) {
529 result.add(nameResolver.getName(index));
530 }
531 return result;
532 }
533
534 @NotNull
535 private Collection<Name> computeEnumMemberNames() {
536 Collection<Name> result = new HashSet<Name>();
537
538 for (JetType supertype : getTypeConstructor().getSupertypes()) {
539 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
540 if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof PropertyDescriptor) {
541 result.add(descriptor.getName());
542 }
543 }
544 }
545
546 final NameResolver nameResolver = deserializer.getNameResolver();
547 return KotlinPackage.mapTo(classProto.getMemberList(), result, new Function1<ProtoBuf.Callable, Name>() {
548 @Override
549 public Name invoke(@NotNull ProtoBuf.Callable callable) {
550 return nameResolver.getName(callable.getName());
551 }
552 });
553 }
554
555 @NotNull
556 public Collection<ClassDescriptor> getAllDescriptors() {
557 Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(nestedClassNames.size() + enumEntryNames.size());
558 for (Name name : nestedClassNames) {
559 ClassDescriptor descriptor = findClass.invoke(name);
560 if (descriptor != null) {
561 result.add(descriptor);
562 }
563 }
564 for (Name name : enumEntryNames) {
565 ClassDescriptor descriptor = findClass.invoke(name);
566 if (descriptor != null) {
567 result.add(descriptor);
568 }
569 }
570 return result;
571 }
572 }
573 }