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