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