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.lang.resolve.lazy.descriptors;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.base.Predicates;
021 import com.google.common.collect.Collections2;
022 import com.google.common.collect.Lists;
023 import com.intellij.psi.PsiElement;
024 import jet.Function0;
025 import jet.Function1;
026 import jet.Unit;
027 import org.jetbrains.annotations.NotNull;
028 import org.jetbrains.annotations.Nullable;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
031 import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase;
032 import org.jetbrains.jet.lang.psi.*;
033 import org.jetbrains.jet.lang.resolve.AnnotationResolver;
034 import org.jetbrains.jet.lang.resolve.BindingContext;
035 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
036 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
037 import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
038 import org.jetbrains.jet.lang.resolve.lazy.LazyDescriptor;
039 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
040 import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
041 import org.jetbrains.jet.lang.resolve.lazy.data.FilteringClassLikeInfo;
042 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
043 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
044 import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider;
045 import org.jetbrains.jet.lang.resolve.name.Name;
046 import org.jetbrains.jet.lang.resolve.scopes.*;
047 import org.jetbrains.jet.lang.types.JetType;
048 import org.jetbrains.jet.lang.types.TypeConstructor;
049 import org.jetbrains.jet.lang.types.TypeUtils;
050 import org.jetbrains.jet.storage.NotNullLazyValue;
051 import org.jetbrains.jet.storage.NullableLazyValue;
052 import org.jetbrains.jet.storage.StorageManager;
053
054 import java.util.*;
055
056 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
057 import static org.jetbrains.jet.lang.resolve.ModifiersChecker.*;
058
059 public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDescriptor, ClassDescriptor {
060
061 private static final Predicate<Object> ONLY_ENUM_ENTRIES = Predicates.instanceOf(JetEnumEntry.class);
062 private static final Predicate<JetType> VALID_SUPERTYPE = new Predicate<JetType>() {
063 @Override
064 public boolean apply(JetType type) {
065 assert !type.isError() : "Error types must be filtered out in DescriptorResolver";
066 return TypeUtils.getClassDescriptor(type) != null;
067 }
068 };
069 private final ResolveSession resolveSession;
070 private final JetClassLikeInfo originalClassInfo;
071 private final ClassMemberDeclarationProvider declarationProvider;
072
073 private final LazyClassTypeConstructor typeConstructor;
074 private final Modality modality;
075 private final Visibility visibility;
076 private final ClassKind kind;
077 private final boolean isInner;
078
079 private final NotNullLazyValue<ReceiverParameterDescriptor> thisAsReceiverParameter;
080 private final NotNullLazyValue<List<AnnotationDescriptor>> annotations;
081 private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
082
083 private final LazyClassMemberScope unsubstitutedMemberScope;
084 private final JetScope unsubstitutedInnerClassesScope;
085
086 private final NotNullLazyValue<JetScope> scopeForClassHeaderResolution;
087 private final NotNullLazyValue<JetScope> scopeForMemberDeclarationResolution;
088 private final NotNullLazyValue<JetScope> scopeForPropertyInitializerResolution;
089
090 public LazyClassDescriptor(
091 @NotNull ResolveSession resolveSession,
092 @NotNull DeclarationDescriptor containingDeclaration,
093 @NotNull Name name,
094 @NotNull JetClassLikeInfo classLikeInfo
095 ) {
096 super(containingDeclaration, name);
097 this.resolveSession = resolveSession;
098
099 if (classLikeInfo.getCorrespondingClassOrObject() != null) {
100 this.resolveSession.getTrace().record(BindingContext.CLASS, classLikeInfo.getCorrespondingClassOrObject(), this);
101 }
102
103 this.originalClassInfo = classLikeInfo;
104 JetClassLikeInfo classLikeInfoForMembers =
105 classLikeInfo.getClassKind() != ClassKind.ENUM_CLASS ? classLikeInfo : noEnumEntries(classLikeInfo);
106 this.declarationProvider =
107 resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfoForMembers);
108
109 this.unsubstitutedMemberScope = new LazyClassMemberScope(resolveSession, declarationProvider, this);
110 this.unsubstitutedInnerClassesScope = new InnerClassesScopeWrapper(unsubstitutedMemberScope);
111
112 this.typeConstructor = new LazyClassTypeConstructor();
113
114 JetModifierList modifierList = classLikeInfo.getModifierList();
115 this.kind = classLikeInfo.getClassKind();
116 if (kind.isObject()) {
117 this.modality = Modality.FINAL;
118 }
119 else {
120 Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL;
121 this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
122 }
123 this.visibility = resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this));
124 this.isInner = isInnerClass(modifierList);
125
126 StorageManager storageManager = resolveSession.getStorageManager();
127 this.thisAsReceiverParameter = storageManager.createLazyValue(new Function0<ReceiverParameterDescriptor>() {
128 @Override
129 public ReceiverParameterDescriptor invoke() {
130 return DescriptorFactory.createLazyReceiverParameterDescriptor(LazyClassDescriptor.this);
131 }
132 });
133 this.annotations = storageManager.createLazyValue(new Function0<List<AnnotationDescriptor>>() {
134 @Override
135 public List<AnnotationDescriptor> invoke() {
136 return resolveAnnotations();
137 }
138 });
139 this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptor>() {
140 @Override
141 public ClassDescriptor invoke() {
142 return computeClassObjectDescriptor();
143 }
144 });
145 this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Function0<JetScope>() {
146 @Override
147 public JetScope invoke() {
148 return computeScopeForClassHeaderResolution();
149 }
150 });
151 this.scopeForMemberDeclarationResolution = storageManager.createLazyValue(new Function0<JetScope>() {
152 @Override
153 public JetScope invoke() {
154 return computeScopeForMemberDeclarationResolution();
155 }
156 });
157 this.scopeForPropertyInitializerResolution = storageManager.createLazyValue(new Function0<JetScope>() {
158 @Override
159 public JetScope invoke() {
160 return computeScopeForPropertyInitializerResolution();
161 }
162 });
163 }
164
165 @Override
166 protected JetScope getScopeForMemberLookup() {
167 return unsubstitutedMemberScope;
168 }
169
170 @NotNull
171 @Override
172 public JetScope getUnsubstitutedInnerClassesScope() {
173 return unsubstitutedInnerClassesScope;
174 }
175
176 @NotNull
177 public JetScope getScopeForClassHeaderResolution() {
178 return scopeForClassHeaderResolution.invoke();
179 }
180
181 @NotNull
182 private JetScope computeScopeForClassHeaderResolution() {
183 WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with type parameters for " + getName());
184 for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
185 scope.addClassifierDescriptor(typeParameterDescriptor);
186 }
187 scope.changeLockLevel(WritableScope.LockLevel.READING);
188
189 PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
190
191 return new ChainedScope(this, "ScopeForClassHeaderResolution: " + getName(),
192 scope,
193 getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
194 }
195
196 @NotNull
197 public JetScope getScopeForMemberDeclarationResolution() {
198 return scopeForMemberDeclarationResolution.invoke();
199 }
200
201 @NotNull
202 private JetScope computeScopeForMemberDeclarationResolution() {
203 WritableScopeImpl thisScope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with 'this' for " + getName());
204 thisScope.addLabeledDeclaration(this);
205 thisScope.changeLockLevel(WritableScope.LockLevel.READING);
206
207 ClassDescriptor classObject = getClassObjectDescriptor();
208 JetScope classObjectAdapterScope = (classObject != null) ? new ClassObjectMixinScope(classObject) : JetScope.EMPTY;
209
210 return new ChainedScope(
211 this,
212 "ScopeForMemberDeclarationResolution: " + getName(),
213 thisScope,
214 getScopeForMemberLookup(),
215 getScopeForClassHeaderResolution(),
216 classObjectAdapterScope);
217 }
218
219 @NotNull
220 public JetScope getScopeForPropertyInitializerResolution() {
221 return scopeForPropertyInitializerResolution.invoke();
222 }
223
224 @NotNull
225 private JetScope computeScopeForPropertyInitializerResolution() {
226 ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
227 if (primaryConstructor == null) return getScopeForMemberDeclarationResolution();
228
229 WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with constructor parameters in " + getName());
230 for (ValueParameterDescriptor valueParameterDescriptor : primaryConstructor.getValueParameters()) {
231 scope.addVariableDescriptor(valueParameterDescriptor);
232 }
233 scope.changeLockLevel(WritableScope.LockLevel.READING);
234
235 return new ChainedScope(
236 this,
237 "ScopeForPropertyInitializerResolution: " + getName(),
238 scope, getScopeForMemberDeclarationResolution());
239 }
240
241 @NotNull
242 @Override
243 public Collection<ConstructorDescriptor> getConstructors() {
244 return unsubstitutedMemberScope.getConstructors();
245 }
246
247 @Override
248 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
249 return unsubstitutedMemberScope.getPrimaryConstructor();
250 }
251
252 @NotNull
253 @Override
254 public TypeConstructor getTypeConstructor() {
255 return typeConstructor;
256 }
257
258 @Override
259 public JetType getClassObjectType() {
260 ClassDescriptor classObjectDescriptor = getClassObjectDescriptor();
261 return classObjectDescriptor == null ? null : classObjectDescriptor.getDefaultType();
262 }
263
264 @Override
265 public ClassDescriptor getClassObjectDescriptor() {
266 return classObjectDescriptor.invoke();
267 }
268
269 @Nullable
270 private ClassDescriptor computeClassObjectDescriptor() {
271 JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
272
273 JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
274 if (classObjectInfo != null) {
275 return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
276 }
277 return null;
278 }
279
280 @Nullable
281 public JetClassLikeInfo getClassObjectInfo(JetClassObject classObject) {
282 if (classObject != null) {
283 if (!DescriptorUtils.inStaticContext(this)) {
284 return null;
285 }
286 JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
287 if (objectDeclaration != null) {
288 return JetClassInfoUtil.createClassLikeInfo(objectDeclaration);
289 }
290 }
291 else {
292 if (getKind() == ClassKind.ENUM_CLASS) {
293 // Enum classes always have class objects, and enum constants are their members
294 return enumClassObjectInfo(originalClassInfo);
295 }
296 }
297 return null;
298 }
299
300 @NotNull
301 @Override
302 public ClassKind getKind() {
303 return kind;
304 }
305
306 @NotNull
307 @Override
308 public Modality getModality() {
309 return modality;
310 }
311
312 @NotNull
313 @Override
314 public Visibility getVisibility() {
315 return visibility;
316 }
317
318 @Override
319 public boolean isInner() {
320 return isInner;
321 }
322
323 @NotNull
324 @Override
325 public ReceiverParameterDescriptor getThisAsReceiverParameter() {
326 return thisAsReceiverParameter.invoke();
327 }
328
329 @Override
330 public List<AnnotationDescriptor> getAnnotations() {
331 return annotations.invoke();
332 }
333
334 @NotNull
335 private List<AnnotationDescriptor> resolveAnnotations() {
336 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
337 JetModifierList modifierList = classInfo.getModifierList();
338 if (modifierList != null) {
339 AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
340 JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
341 return annotationResolver.resolveAnnotationsWithArguments(scopeForDeclaration, modifierList, resolveSession.getTrace());
342 }
343 else {
344 return Collections.emptyList();
345 }
346 }
347
348 @Override
349 public String toString() {
350 return "lazy class " + getName().toString();
351 }
352
353 @Override
354 public void forceResolveAllContents() {
355 getAnnotations();
356 getClassObjectDescriptor();
357 getClassObjectType();
358 getConstructors();
359 getContainingDeclaration();
360 getThisAsReceiverParameter();
361 getKind();
362 getModality();
363 getName();
364 getOriginal();
365 getScopeForClassHeaderResolution();
366 getScopeForMemberDeclarationResolution();
367 ForceResolveUtil.forceResolveAllContents(getScopeForMemberLookup());
368 getScopeForPropertyInitializerResolution();
369 getUnsubstitutedInnerClassesScope();
370 ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
371 getUnsubstitutedPrimaryConstructor();
372 getVisibility();
373 }
374
375 private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor {
376 private final NotNullLazyValue<Collection<JetType>> supertypes = resolveSession.getStorageManager().createLazyValueWithPostCompute(
377 new Function0<Collection<JetType>>() {
378 @Override
379 public Collection<JetType> invoke() {
380 if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) {
381 return Collections.emptyList();
382 }
383 else {
384 JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
385 if (classOrObject == null) {
386 return Collections.emptyList();
387 }
388 else {
389 List<JetType> allSupertypes = resolveSession.getInjector().getDescriptorResolver()
390 .resolveSupertypes(getScopeForClassHeaderResolution(),
391 LazyClassDescriptor.this, classOrObject,
392 resolveSession.getTrace());
393
394 return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
395 }
396 }
397 }
398 },
399 new Function1<Boolean, Collection<JetType>>() {
400 @Override
401 public Collection<JetType> invoke(Boolean firstTime) {
402 return Collections.emptyList();
403 }
404 },
405 new Function1<Collection<JetType>, Unit>() {
406 @Override
407 public Unit invoke(@NotNull Collection<JetType> supertypes) {
408 findAndDisconnectLoopsInTypeHierarchy(supertypes);
409 return Unit.VALUE;
410 }
411 });
412
413 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = resolveSession.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
414 @Override
415 public List<TypeParameterDescriptor> invoke() {
416 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
417 List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
418
419 List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
420 for (int i = 0; i < typeParameters.size(); i++) {
421 parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i));
422 }
423
424 return parameters;
425 }
426 });
427
428 @NotNull
429 @Override
430 public List<TypeParameterDescriptor> getParameters() {
431 return parameters.invoke();
432 }
433
434 @NotNull
435 @Override
436 public Collection<JetType> getSupertypes() {
437 return supertypes.invoke();
438 }
439
440 private void findAndDisconnectLoopsInTypeHierarchy(Collection<JetType> supertypes) {
441 for (Iterator<JetType> iterator = supertypes.iterator(); iterator.hasNext(); ) {
442 JetType supertype = iterator.next();
443 if (isReachable(supertype.getConstructor(), this, new HashSet<TypeConstructor>())) {
444 iterator.remove();
445 }
446 }
447 }
448
449 private boolean isReachable(TypeConstructor from, TypeConstructor to, Set<TypeConstructor> visited) {
450 if (!visited.add(from)) return false;
451 for (JetType supertype : from.getSupertypes()) {
452 TypeConstructor supertypeConstructor = supertype.getConstructor();
453 if (supertypeConstructor == to) {
454 return true;
455 }
456 if (isReachable(supertypeConstructor, to, visited)) {
457 return true;
458 }
459 }
460 return false;
461 }
462
463 @Override
464 public boolean isFinal() {
465 return !getModality().isOverridable();
466 }
467
468 @Override
469 public boolean isDenotable() {
470 return true;
471 }
472
473 @Override
474 public ClassifierDescriptor getDeclarationDescriptor() {
475 return LazyClassDescriptor.this;
476 }
477
478 @Override
479 public List<AnnotationDescriptor> getAnnotations() {
480 return Collections.emptyList(); // TODO
481 }
482
483 @Override
484 public String toString() {
485 return LazyClassDescriptor.this.getName().toString();
486 }
487
488 @Override
489 public void forceResolveAllContents() {
490 getAnnotations();
491 getSupertypes();
492 getParameters();
493 }
494 }
495
496 private JetClassLikeInfo noEnumEntries(JetClassLikeInfo classLikeInfo) {
497 return new FilteringClassLikeInfo(resolveSession.getStorageManager(), classLikeInfo, Predicates.not(ONLY_ENUM_ENTRIES));
498 }
499
500 private JetClassLikeInfo enumClassObjectInfo(JetClassLikeInfo classLikeInfo) {
501 return new FilteringClassLikeInfo(resolveSession.getStorageManager(), classLikeInfo, ONLY_ENUM_ENTRIES) {
502 @Override
503 public JetClassOrObject getCorrespondingClassOrObject() {
504 return null;
505 }
506
507 @NotNull
508 @Override
509 public ClassKind getClassKind() {
510 return ClassKind.CLASS_OBJECT;
511 }
512
513 @NotNull
514 @Override
515 public List<? extends JetParameter> getPrimaryConstructorParameters() {
516 return Collections.emptyList();
517 }
518
519 @NotNull
520 @Override
521 public List<JetTypeParameter> getTypeParameters() {
522 return Collections.emptyList();
523 }
524 };
525 }
526
527 private ScopeProvider getScopeProvider() {
528 return resolveSession.getInjector().getScopeProvider();
529 }
530
531 }