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