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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.collect.Lists; 020import com.google.common.collect.Multimap; 021import com.google.common.collect.Sets; 022import com.intellij.psi.PsiElement; 023import com.intellij.psi.PsiNameIdentifierOwner; 024import com.intellij.util.containers.ContainerUtil; 025import org.jetbrains.annotations.NotNull; 026import org.jetbrains.annotations.Nullable; 027import org.jetbrains.jet.lang.descriptors.*; 028import org.jetbrains.jet.lang.descriptors.impl.*; 029import org.jetbrains.jet.lang.psi.*; 030import org.jetbrains.jet.lang.resolve.name.Name; 031import org.jetbrains.jet.lang.resolve.scopes.*; 032import org.jetbrains.jet.lang.types.JetType; 033import org.jetbrains.jet.lang.types.SubstitutionUtils; 034import org.jetbrains.jet.lang.types.TypeConstructor; 035import org.jetbrains.jet.lang.types.TypeProjection; 036import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 037import org.jetbrains.jet.utils.DFS; 038 039import javax.inject.Inject; 040import java.util.*; 041 042import static org.jetbrains.jet.lang.diagnostics.Errors.*; 043import static org.jetbrains.jet.lang.resolve.BindingContext.FQNAME_TO_CLASS_DESCRIPTOR; 044import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE; 045import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; 046 047public 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}