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