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