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