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