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