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;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Multimap;
021 import com.google.common.collect.Sets;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.PsiNameIdentifierOwner;
024 import com.intellij.util.containers.ContainerUtil;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.impl.*;
029 import org.jetbrains.jet.lang.psi.*;
030 import org.jetbrains.jet.lang.resolve.name.Name;
031 import org.jetbrains.jet.lang.resolve.scopes.*;
032 import org.jetbrains.jet.lang.types.JetType;
033 import org.jetbrains.jet.lang.types.SubstitutionUtils;
034 import org.jetbrains.jet.lang.types.TypeConstructor;
035 import org.jetbrains.jet.lang.types.TypeProjection;
036 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
037 import org.jetbrains.jet.utils.DFS;
038
039 import javax.inject.Inject;
040 import java.util.*;
041
042 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
043 import static org.jetbrains.jet.lang.resolve.BindingContext.FQNAME_TO_CLASS_DESCRIPTOR;
044 import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
045 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
046
047 public class TypeHierarchyResolver {
048 @NotNull
049 private TopDownAnalysisContext context;
050 @NotNull
051 private ImportsResolver importsResolver;
052 @NotNull
053 private DescriptorResolver descriptorResolver;
054 @NotNull
055 private ScriptHeaderResolver scriptHeaderResolver;
056 @NotNull
057 private NamespaceFactoryImpl namespaceFactory;
058 @NotNull
059 private BindingTrace trace;
060
061 @Inject
062 public void setContext(@NotNull TopDownAnalysisContext context) {
063 this.context = context;
064 }
065
066 @Inject
067 public void setImportsResolver(@NotNull ImportsResolver importsResolver) {
068 this.importsResolver = importsResolver;
069 }
070
071 @Inject
072 public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) {
073 this.descriptorResolver = descriptorResolver;
074 }
075
076 @Inject
077 public void setScriptHeaderResolver(@NotNull ScriptHeaderResolver scriptHeaderResolver) {
078 this.scriptHeaderResolver = scriptHeaderResolver;
079 }
080
081 @Inject
082 public void setNamespaceFactory(@NotNull NamespaceFactoryImpl namespaceFactory) {
083 this.namespaceFactory = namespaceFactory;
084 }
085
086 @Inject
087 public void setTrace(@NotNull BindingTrace trace) {
088 this.trace = trace;
089 }
090
091 public void process(
092 @NotNull JetScope outerScope, @NotNull NamespaceLikeBuilder owner,
093 @NotNull Collection<? extends PsiElement> declarations
094 ) {
095
096 {
097 // TODO: Very temp code - main goal is to remove recursion from collectNamespacesAndClassifiers
098 Queue<JetDeclarationContainer> forDeferredResolve = new LinkedList<JetDeclarationContainer>();
099 forDeferredResolve.addAll(collectNamespacesAndClassifiers(outerScope, owner, declarations));
100
101 while (!forDeferredResolve.isEmpty()) {
102 JetDeclarationContainer declarationContainer = forDeferredResolve.poll();
103 assert declarationContainer != null;
104
105 DeclarationDescriptor descriptorForDeferredResolve = context.forDeferredResolver.get(declarationContainer);
106 JetScope scope = context.normalScope.get(declarationContainer);
107
108 // Even more temp code
109 if (descriptorForDeferredResolve instanceof MutableClassDescriptorLite) {
110 forDeferredResolve.addAll(
111 collectNamespacesAndClassifiers(
112 scope,
113 ((MutableClassDescriptorLite) descriptorForDeferredResolve).getBuilder(),
114 declarationContainer.getDeclarations()));
115 }
116 else if (descriptorForDeferredResolve instanceof NamespaceDescriptorImpl) {
117 forDeferredResolve.addAll(
118 collectNamespacesAndClassifiers(
119 scope,
120 ((NamespaceDescriptorImpl) descriptorForDeferredResolve).getBuilder(),
121 declarationContainer.getDeclarations()));
122 }
123 else {
124 assert false;
125 }
126 }
127 }
128
129 importsResolver.processTypeImports(outerScope);
130
131 createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
132 resolveTypesInClassHeaders(); // Generic bounds and types in supertype lists (no expressions or constructor resolution)
133
134 context.setClassesTopologicalOrder(topologicallySortClassesAndObjects());
135
136 // Detect and disconnect all loops in the hierarchy
137 detectAndDisconnectLoops();
138
139 // At this point, there are no loops in the type hierarchy
140
141 checkSupertypesForConsistency();
142 // computeSuperclasses();
143
144 checkTypesInClassHeaders(); // Check bounds in the types used in generic bounds and supertype lists
145 }
146
147 @Nullable
148 private Collection<JetDeclarationContainer> collectNamespacesAndClassifiers(
149 @NotNull JetScope outerScope,
150 @NotNull NamespaceLikeBuilder owner,
151 @NotNull Iterable<? extends PsiElement> declarations
152 ) {
153 Collection<JetDeclarationContainer> forDeferredResolve = new ArrayList<JetDeclarationContainer>();
154
155 ClassifierCollector collector = new ClassifierCollector(outerScope, owner, forDeferredResolve);
156
157 for (PsiElement declaration : declarations) {
158 declaration.accept(collector);
159 }
160
161 return forDeferredResolve;
162 }
163
164
165 @NotNull
166 private static ClassKind getClassKind(@NotNull JetClass jetClass) {
167 if (jetClass.isTrait()) return ClassKind.TRAIT;
168 if (jetClass.isAnnotation()) return ClassKind.ANNOTATION_CLASS;
169 if (jetClass.isEnum()) return ClassKind.ENUM_CLASS;
170 return ClassKind.CLASS;
171 }
172
173 private void createTypeConstructors() {
174 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
175 JetClass jetClass = entry.getKey();
176 MutableClassDescriptor descriptor = entry.getValue();
177 descriptorResolver.resolveMutableClassDescriptor(jetClass, descriptor, trace);
178 descriptor.createTypeConstructor();
179 }
180 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
181 JetObjectDeclaration objectDeclaration = entry.getKey();
182 MutableClassDescriptor descriptor = entry.getValue();
183 descriptor.setModality(Modality.FINAL);
184 descriptor.setVisibility(ModifiersChecker.resolveVisibilityFromModifiers(objectDeclaration));
185 descriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
186 descriptor.createTypeConstructor();
187 }
188 }
189
190 private void resolveTypesInClassHeaders() {
191 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
192 JetClass jetClass = entry.getKey();
193 MutableClassDescriptor descriptor = entry.getValue();
194 descriptorResolver.resolveGenericBounds(jetClass, descriptor.getScopeForSupertypeResolution(),
195 (List) descriptor.getTypeConstructor().getParameters(), trace);
196 descriptorResolver.resolveSupertypesForMutableClassDescriptor(jetClass, descriptor, trace);
197 }
198 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
199 JetClassOrObject jetClass = entry.getKey();
200 MutableClassDescriptor descriptor = entry.getValue();
201 descriptorResolver.resolveSupertypesForMutableClassDescriptor(jetClass, descriptor, trace);
202 }
203 }
204
205 private List<MutableClassDescriptorLite> topologicallySortClassesAndObjects() {
206 // A topsort is needed only for better diagnostics:
207 // edges that get removed to disconnect loops are more reasonable in this case
208 return DFS.topologicalOrder(
209 ContainerUtil.<MutableClassDescriptorLite>concat(context.getClasses().values(), context.getObjects().values()),
210 new DFS.Neighbors<MutableClassDescriptorLite>() {
211 @NotNull
212 @Override
213 public Iterable<MutableClassDescriptorLite> getNeighbors(MutableClassDescriptorLite current) {
214 List<MutableClassDescriptorLite> result = Lists.newArrayList();
215 for (JetType supertype : current.getSupertypes()) {
216 DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
217 if (declarationDescriptor instanceof MutableClassDescriptorLite) {
218 MutableClassDescriptorLite classDescriptor = (MutableClassDescriptorLite) declarationDescriptor;
219 result.add(classDescriptor);
220 }
221 }
222 return result;
223 }
224 });
225
226 }
227
228 private void detectAndDisconnectLoops() {
229 // Loop detection and disconnection
230 Set<ClassDescriptor> visited = Sets.newHashSet();
231 Set<ClassDescriptor> beingProcessed = Sets.newHashSet();
232 List<ClassDescriptor> currentPath = Lists.newArrayList();
233 for (MutableClassDescriptorLite klass : context.getClassesTopologicalOrder()) {
234 traverseTypeHierarchy(klass, visited, beingProcessed, currentPath);
235 }
236 }
237
238 private void traverseTypeHierarchy(
239 MutableClassDescriptorLite currentClass,
240 Set<ClassDescriptor> visited,
241 Set<ClassDescriptor> beingProcessed,
242 List<ClassDescriptor> currentPath
243 ) {
244 if (!visited.add(currentClass)) {
245 if (beingProcessed.contains(currentClass)) {
246 markCycleErrors(currentPath, currentClass);
247 assert !currentPath.isEmpty() : "Cycle cannot be found on an empty currentPath";
248 ClassDescriptor subclassOfCurrent = currentPath.get(currentPath.size() - 1);
249 assert subclassOfCurrent instanceof MutableClassDescriptor;
250 // Disconnect the loop
251 for (Iterator<JetType> iterator = ((MutableClassDescriptor) subclassOfCurrent).getSupertypes().iterator();
252 iterator.hasNext(); ) {
253 JetType type = iterator.next();
254 if (type.getConstructor() == currentClass.getTypeConstructor()) {
255 iterator.remove();
256 break;
257 }
258 }
259 }
260 return;
261 }
262
263 beingProcessed.add(currentClass);
264 currentPath.add(currentClass);
265 for (JetType supertype : Lists.newArrayList(currentClass.getSupertypes())) {
266 DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
267 if (declarationDescriptor instanceof MutableClassDescriptor) {
268 MutableClassDescriptor mutableClassDescriptor = (MutableClassDescriptor) declarationDescriptor;
269 traverseTypeHierarchy(mutableClassDescriptor, visited, beingProcessed, currentPath);
270 }
271 }
272 beingProcessed.remove(currentClass);
273 currentPath.remove(currentPath.size() - 1);
274 }
275
276 private void markCycleErrors(List<ClassDescriptor> currentPath, @NotNull ClassDescriptor current) {
277 int size = currentPath.size();
278 for (int i = size - 1; i >= 0; i--) {
279 ClassDescriptor classDescriptor = currentPath.get(i);
280
281 ClassDescriptor superclass = (i < size - 1) ? currentPath.get(i + 1) : current;
282 PsiElement psiElement = BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
283
284 PsiElement elementToMark = null;
285 if (psiElement instanceof JetClassOrObject) {
286 JetClassOrObject classOrObject = (JetClassOrObject) psiElement;
287 for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
288 JetTypeReference typeReference = delegationSpecifier.getTypeReference();
289 if (typeReference == null) continue;
290 JetType supertype = trace.get(TYPE, typeReference);
291 if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
292 elementToMark = typeReference;
293 }
294 }
295 }
296 if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
297 PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
298 PsiElement nameIdentifier = namedElement.getNameIdentifier();
299 if (nameIdentifier != null) {
300 elementToMark = nameIdentifier;
301 }
302 }
303 if (elementToMark != null) {
304 trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
305 }
306
307 if (classDescriptor == current) {
308 // Beginning of cycle is found
309 break;
310 }
311 }
312 }
313
314 private void checkSupertypesForConsistency() {
315 for (MutableClassDescriptorLite mutableClassDescriptor : context.getClassesTopologicalOrder()) {
316 Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils
317 .buildDeepSubstitutionMultimap(mutableClassDescriptor.getDefaultType());
318 for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
319 Collection<TypeProjection> projections = entry.getValue();
320 if (projections.size() > 1) {
321 TypeConstructor typeConstructor = entry.getKey();
322 DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
323 assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
324 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
325
326 // Immediate arguments of supertypes cannot be projected
327 Set<JetType> conflictingTypes = Sets.newLinkedHashSet();
328 for (TypeProjection projection : projections) {
329 conflictingTypes.add(projection.getType());
330 }
331 switch (typeParameterDescriptor.getVariance()) {
332 case INVARIANT:
333 // Leave conflicting types as is
334 break;
335 case IN_VARIANCE:
336 // Filter out those who have supertypes in this set (common supertype)
337 Filter.REMOVE_IF_SUPERTYPE_IN_THE_SET.proceed(conflictingTypes);
338 break;
339 case OUT_VARIANCE:
340 // Filter out those who have subtypes in this set (common subtype)
341 Filter.REMOVE_IF_SUBTYPE_IN_THE_SET.proceed(conflictingTypes);
342 break;
343 }
344
345 if (conflictingTypes.size() > 1) {
346 DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
347 assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
348 JetClassOrObject psiElement = (JetClassOrObject) BindingContextUtils
349 .classDescriptorToDeclaration(trace.getBindingContext(), mutableClassDescriptor);
350 JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList();
351 assert delegationSpecifierList != null;
352 // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes);
353 trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES
354 .on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration,
355 conflictingTypes));
356 }
357 }
358 }
359 }
360 }
361
362 private enum Filter {
363 REMOVE_IF_SUBTYPE_IN_THE_SET {
364 @Override
365 public boolean removeNeeded(JetType subject, JetType other) {
366 return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject);
367 }
368 },
369 REMOVE_IF_SUPERTYPE_IN_THE_SET {
370 @Override
371 public boolean removeNeeded(JetType subject, JetType other) {
372 return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other);
373 }
374 };
375
376 private void proceed(Set<JetType> conflictingTypes) {
377 for (Iterator<JetType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) {
378 JetType type = iterator.next();
379 for (JetType otherType : conflictingTypes) {
380 boolean subtypeOf = removeNeeded(type, otherType);
381 if (type != otherType && subtypeOf) {
382 iterator.remove();
383 break;
384 }
385 }
386 }
387 }
388
389 public abstract boolean removeNeeded(JetType subject, JetType other);
390 }
391
392 private void checkTypesInClassHeaders() {
393 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
394 JetClass jetClass = entry.getKey();
395
396 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
397 JetTypeReference typeReference = delegationSpecifier.getTypeReference();
398 if (typeReference != null) {
399 JetType type = trace.getBindingContext().get(TYPE, typeReference);
400 if (type != null) {
401 descriptorResolver.checkBounds(typeReference, type, trace);
402 }
403 }
404 }
405
406 for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
407 JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
408 if (extendsBound != null) {
409 JetType type = trace.getBindingContext().get(TYPE, extendsBound);
410 if (type != null) {
411 descriptorResolver.checkBounds(extendsBound, type, trace);
412 }
413 }
414 }
415
416 for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) {
417 JetTypeReference extendsBound = constraint.getBoundTypeReference();
418 if (extendsBound != null) {
419 JetType type = trace.getBindingContext().get(TYPE, extendsBound);
420 if (type != null) {
421 descriptorResolver.checkBounds(extendsBound, type, trace);
422 }
423 }
424 }
425 }
426 }
427
428 private class ClassifierCollector extends JetVisitorVoid {
429 private final JetScope outerScope;
430 private final NamespaceLikeBuilder owner;
431 private final Collection<JetDeclarationContainer> forDeferredResolve;
432
433 public ClassifierCollector(@NotNull JetScope outerScope,
434 @NotNull NamespaceLikeBuilder owner,
435 @NotNull Collection<JetDeclarationContainer> forDeferredResolve
436 ) {
437 this.outerScope = outerScope;
438 this.owner = owner;
439 this.forDeferredResolve = forDeferredResolve;
440 }
441
442 @Override
443 public void visitJetFile(JetFile file) {
444 NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded(
445 file, outerScope, RedeclarationHandler.DO_NOTHING);
446 context.getNamespaceDescriptors().put(file, namespaceDescriptor);
447
448 WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(),
449 new TraceBasedRedeclarationHandler(trace), "namespace");
450 namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
451 context.getNamespaceScopes().put(file, namespaceScope);
452
453 if (file.isScript()) {
454 scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
455 }
456
457 prepareForDeferredCall(namespaceScope, namespaceDescriptor, file);
458 }
459
460 @Override
461 public void visitClass(JetClass klass) {
462 MutableClassDescriptor mutableClassDescriptor = createClassDescriptorForClass(klass, owner.getOwnerForChildren());
463
464 owner.addClassifierDescriptor(mutableClassDescriptor);
465 }
466
467 @Override
468 public void visitObjectDeclaration(JetObjectDeclaration declaration) {
469 MutableClassDescriptor objectDescriptor =
470 createClassDescriptorForObject(declaration, owner, outerScope, JetPsiUtil.safeName(declaration.getName()),
471 ClassKind.OBJECT);
472 owner.addObjectDescriptor(objectDescriptor);
473 trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), objectDescriptor);
474 }
475
476 @Override
477 public void visitEnumEntry(JetEnumEntry enumEntry) {
478 // TODO: Bad casting
479 MutableClassDescriptorLite ownerClassDescriptor = (MutableClassDescriptorLite) owner.getOwnerForChildren();
480 MutableClassDescriptorLite classObjectDescriptor = ownerClassDescriptor.getClassObjectDescriptor();
481
482 assert classObjectDescriptor != null : enumEntry.getParent().getText();
483 createClassDescriptorForEnumEntry(enumEntry, classObjectDescriptor);
484 }
485
486 @Override
487 public void visitTypedef(JetTypedef typedef) {
488 trace.report(UNSUPPORTED.on(typedef, "TypeHierarchyResolver"));
489 }
490
491 @Override
492 public void visitClassObject(JetClassObject classObject) {
493 JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
494 if (objectDeclaration != null) {
495 Name classObjectName = getClassObjectName(owner.getOwnerForChildren().getName());
496
497 MutableClassDescriptor classObjectDescriptor = createClassDescriptorForObject(
498 objectDeclaration, owner, outerScope,
499 classObjectName, ClassKind.CLASS_OBJECT);
500
501 NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
502 switch (status) {
503 case DUPLICATE:
504 trace.report(MANY_CLASS_OBJECTS.on(classObject));
505 break;
506 case NOT_ALLOWED:
507 trace.report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
508 break;
509 case OK:
510 // Everything is OK so no errors to trace.
511 break;
512 }
513 }
514 }
515
516 private void createClassObjectForEnumClass(JetClass klass, MutableClassDescriptor mutableClassDescriptor) {
517 if (mutableClassDescriptor.getKind() == ClassKind.ENUM_CLASS) {
518 MutableClassDescriptor classObjectDescriptor =
519 createClassObjectDescriptor(mutableClassDescriptor, ModifiersChecker.resolveVisibilityFromModifiers(klass));
520 mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
521 classObjectDescriptor.getBuilder().addFunctionDescriptor(
522 DescriptorResolver.createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
523 classObjectDescriptor.getBuilder().addFunctionDescriptor(
524 DescriptorResolver.createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
525 }
526 }
527
528 @NotNull
529 private MutableClassDescriptor createClassObjectDescriptor(
530 @NotNull ClassDescriptor classDescriptor,
531 @NotNull Visibility visibility
532 ) {
533 MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(
534 classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false, getClassObjectName(classDescriptor.getName()));
535 classObjectDescriptor.setModality(Modality.FINAL);
536 classObjectDescriptor.setVisibility(visibility);
537 classObjectDescriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
538 classObjectDescriptor.createTypeConstructor();
539 ConstructorDescriptorImpl primaryConstructorForObject = createPrimaryConstructorForObject(null, classObjectDescriptor);
540 primaryConstructorForObject.setReturnType(classObjectDescriptor.getDefaultType());
541 return classObjectDescriptor;
542 }
543
544 @NotNull
545 private MutableClassDescriptor createClassDescriptorForClass(
546 @NotNull JetClass klass,
547 @NotNull DeclarationDescriptor containingDeclaration
548 ) {
549 ClassKind kind = getClassKind(klass);
550 // Kind check is needed in order to not consider enums as inner in any case
551 // (otherwise it would be impossible to create a class object in the enum)
552 boolean isInner = kind == ClassKind.CLASS && klass.isInner();
553 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
554 containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName()));
555 context.getClasses().put(klass, mutableClassDescriptor);
556 trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(klass), mutableClassDescriptor);
557
558 createClassObjectForEnumClass(klass, mutableClassDescriptor);
559
560 JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
561
562 prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
563
564 return mutableClassDescriptor;
565 }
566
567 @NotNull
568 private MutableClassDescriptor createClassDescriptorForObject(
569 @NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner,
570 @NotNull JetScope scope, @NotNull Name name, @NotNull ClassKind kind
571 ) {
572 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
573 owner.getOwnerForChildren(), scope, kind, false, name);
574
575 context.getObjects().put(declaration, mutableClassDescriptor);
576
577 JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
578
579 prepareForDeferredCall(classScope, mutableClassDescriptor, declaration);
580
581 createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
582 trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
583 return mutableClassDescriptor;
584 }
585
586 private MutableClassDescriptor createClassDescriptorForEnumEntry(
587 @NotNull JetEnumEntry declaration,
588 @NotNull MutableClassDescriptorLite classObjectDescriptor
589 ) {
590 NamespaceLikeBuilder owner = classObjectDescriptor.getBuilder();
591 MutableClassDescriptor mutableClassObjectDescriptor = (MutableClassDescriptor) classObjectDescriptor;
592
593 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
594 owner.getOwnerForChildren(), mutableClassObjectDescriptor.getScopeForMemberResolution(), ClassKind.ENUM_ENTRY,
595 false, JetPsiUtil.safeName(declaration.getName()));
596 context.getClasses().put(declaration, mutableClassDescriptor);
597
598 prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
599
600 // ??? - is enum entry object?
601 createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
602 owner.addObjectDescriptor(mutableClassDescriptor);
603 trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
604 return mutableClassDescriptor;
605 }
606
607 private ConstructorDescriptorImpl createPrimaryConstructorForObject(
608 @Nullable PsiElement object,
609 MutableClassDescriptor mutableClassDescriptor
610 ) {
611 ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
612 .createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
613 mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor, trace);
614 return constructorDescriptor;
615 }
616
617 private void prepareForDeferredCall(
618 @NotNull JetScope outerScope,
619 @NotNull DeclarationDescriptor descriptorForDeferredResolve,
620 @NotNull JetDeclarationContainer container
621 ) {
622 forDeferredResolve.add(container);
623 context.normalScope.put(container, outerScope);
624 context.forDeferredResolver.put(container, descriptorForDeferredResolve);
625 }
626 }
627 }