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.DescriptorUtils.getClassObjectName;
049 import static org.jetbrains.jet.lang.resolve.ModifiersChecker.getDefaultClassVisibility;
050 import static org.jetbrains.jet.lang.resolve.ModifiersChecker.resolveVisibilityFromModifiers;
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 (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
399 JetClass jetClass = entry.getKey();
400
401 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
402 JetTypeReference typeReference = delegationSpecifier.getTypeReference();
403 if (typeReference != null) {
404 JetType type = trace.getBindingContext().get(TYPE, typeReference);
405 if (type != null) {
406 descriptorResolver.checkBounds(typeReference, type, trace);
407 }
408 }
409 }
410
411 for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
412 JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
413 if (extendsBound != null) {
414 JetType type = trace.getBindingContext().get(TYPE, extendsBound);
415 if (type != null) {
416 descriptorResolver.checkBounds(extendsBound, type, trace);
417 }
418 }
419 }
420
421 for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) {
422 JetTypeReference extendsBound = constraint.getBoundTypeReference();
423 if (extendsBound != null) {
424 JetType type = trace.getBindingContext().get(TYPE, extendsBound);
425 if (type != null) {
426 descriptorResolver.checkBounds(extendsBound, type, trace);
427 }
428 }
429 }
430 }
431 }
432
433 private class ClassifierCollector extends JetVisitorVoid {
434 private final JetScope outerScope;
435 private final NamespaceLikeBuilder owner;
436 private final Collection<JetDeclarationContainer> forDeferredResolve;
437
438 public ClassifierCollector(@NotNull JetScope outerScope,
439 @NotNull NamespaceLikeBuilder owner,
440 @NotNull Collection<JetDeclarationContainer> forDeferredResolve
441 ) {
442 this.outerScope = outerScope;
443 this.owner = owner;
444 this.forDeferredResolve = forDeferredResolve;
445 }
446
447 @Override
448 public void visitJetFile(JetFile file) {
449 NamespaceDescriptorImpl namespaceDescriptor = namespaceFactory.createNamespaceDescriptorPathIfNeeded(
450 file, outerScope, RedeclarationHandler.DO_NOTHING);
451 context.getNamespaceDescriptors().put(file, namespaceDescriptor);
452
453 WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(),
454 new TraceBasedRedeclarationHandler(trace), "namespace");
455 namespaceScope.changeLockLevel(WritableScope.LockLevel.BOTH);
456 context.getNamespaceScopes().put(file, namespaceScope);
457
458 if (file.isScript()) {
459 scriptHeaderResolver.processScriptHierarchy(file.getScript(), namespaceScope);
460 }
461
462 prepareForDeferredCall(namespaceScope, namespaceDescriptor, file);
463 }
464
465 @Override
466 public void visitClass(JetClass klass) {
467 MutableClassDescriptor mutableClassDescriptor = createClassDescriptorForClass(klass, owner.getOwnerForChildren());
468
469 owner.addClassifierDescriptor(mutableClassDescriptor);
470 }
471
472 @Override
473 public void visitObjectDeclaration(JetObjectDeclaration declaration) {
474 MutableClassDescriptor objectDescriptor =
475 createClassDescriptorForObject(declaration, owner, outerScope, JetPsiUtil.safeName(declaration.getName()),
476 ClassKind.OBJECT);
477 owner.addObjectDescriptor(objectDescriptor);
478 trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(declaration), objectDescriptor);
479 }
480
481 @Override
482 public void visitEnumEntry(JetEnumEntry enumEntry) {
483 // TODO: Bad casting
484 MutableClassDescriptorLite ownerClassDescriptor = (MutableClassDescriptorLite) owner.getOwnerForChildren();
485 MutableClassDescriptorLite classObjectDescriptor = ownerClassDescriptor.getClassObjectDescriptor();
486
487 assert classObjectDescriptor != null : enumEntry.getParent().getText();
488 createClassDescriptorForEnumEntry(enumEntry, classObjectDescriptor);
489 }
490
491 @Override
492 public void visitTypedef(JetTypedef typedef) {
493 trace.report(UNSUPPORTED.on(typedef, "TypeHierarchyResolver"));
494 }
495
496 @Override
497 public void visitClassObject(JetClassObject classObject) {
498 JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
499 if (objectDeclaration != null) {
500 Name classObjectName = getClassObjectName(owner.getOwnerForChildren().getName());
501
502 MutableClassDescriptor classObjectDescriptor = createClassDescriptorForObject(
503 objectDeclaration, owner, outerScope,
504 classObjectName, ClassKind.CLASS_OBJECT);
505
506 NamespaceLikeBuilder.ClassObjectStatus status = owner.setClassObjectDescriptor(classObjectDescriptor);
507 switch (status) {
508 case DUPLICATE:
509 trace.report(MANY_CLASS_OBJECTS.on(classObject));
510 break;
511 case NOT_ALLOWED:
512 trace.report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
513 break;
514 case OK:
515 // Everything is OK so no errors to trace.
516 break;
517 }
518 }
519 }
520
521 private void createClassObjectForEnumClass(JetClass klass, MutableClassDescriptor mutableClassDescriptor) {
522 if (mutableClassDescriptor.getKind() == ClassKind.ENUM_CLASS) {
523 MutableClassDescriptor classObjectDescriptor =
524 createClassObjectDescriptor(mutableClassDescriptor, resolveVisibilityFromModifiers(klass));
525 mutableClassDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor);
526 classObjectDescriptor.getBuilder().addFunctionDescriptor(
527 DescriptorResolver.createEnumClassObjectValuesMethod(classObjectDescriptor, trace));
528 classObjectDescriptor.getBuilder().addFunctionDescriptor(
529 DescriptorResolver.createEnumClassObjectValueOfMethod(classObjectDescriptor, trace));
530 }
531 }
532
533 @NotNull
534 private MutableClassDescriptor createClassObjectDescriptor(
535 @NotNull ClassDescriptor classDescriptor,
536 @NotNull Visibility visibility
537 ) {
538 MutableClassDescriptor classObjectDescriptor = new MutableClassDescriptor(
539 classDescriptor, outerScope, ClassKind.CLASS_OBJECT, false, getClassObjectName(classDescriptor.getName()));
540 classObjectDescriptor.setModality(Modality.FINAL);
541 classObjectDescriptor.setVisibility(visibility);
542 classObjectDescriptor.setTypeParameterDescriptors(new ArrayList<TypeParameterDescriptor>(0));
543 classObjectDescriptor.createTypeConstructor();
544 ConstructorDescriptorImpl primaryConstructorForObject = createPrimaryConstructorForObject(null, classObjectDescriptor);
545 primaryConstructorForObject.setReturnType(classObjectDescriptor.getDefaultType());
546 return classObjectDescriptor;
547 }
548
549 @NotNull
550 private MutableClassDescriptor createClassDescriptorForClass(
551 @NotNull JetClass klass,
552 @NotNull DeclarationDescriptor containingDeclaration
553 ) {
554 ClassKind kind = getClassKind(klass);
555 // Kind check is needed in order to not consider enums as inner in any case
556 // (otherwise it would be impossible to create a class object in the enum)
557 boolean isInner = kind == ClassKind.CLASS && klass.isInner();
558 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
559 containingDeclaration, outerScope, kind, isInner, JetPsiUtil.safeName(klass.getName()));
560 context.getClasses().put(klass, mutableClassDescriptor);
561 trace.record(FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getFQName(klass), mutableClassDescriptor);
562
563 createClassObjectForEnumClass(klass, mutableClassDescriptor);
564
565 JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
566
567 prepareForDeferredCall(classScope, mutableClassDescriptor, klass);
568
569 return mutableClassDescriptor;
570 }
571
572 @NotNull
573 private MutableClassDescriptor createClassDescriptorForObject(
574 @NotNull JetObjectDeclaration declaration, @NotNull NamespaceLikeBuilder owner,
575 @NotNull JetScope scope, @NotNull Name name, @NotNull ClassKind kind
576 ) {
577 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
578 owner.getOwnerForChildren(), scope, kind, false, name);
579
580 context.getObjects().put(declaration, mutableClassDescriptor);
581
582 JetScope classScope = mutableClassDescriptor.getScopeForMemberResolution();
583
584 prepareForDeferredCall(classScope, mutableClassDescriptor, declaration);
585
586 createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
587 trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
588 return mutableClassDescriptor;
589 }
590
591 private MutableClassDescriptor createClassDescriptorForEnumEntry(
592 @NotNull JetEnumEntry declaration,
593 @NotNull MutableClassDescriptorLite classObjectDescriptor
594 ) {
595 NamespaceLikeBuilder owner = classObjectDescriptor.getBuilder();
596 MutableClassDescriptor mutableClassObjectDescriptor = (MutableClassDescriptor) classObjectDescriptor;
597
598 MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(
599 owner.getOwnerForChildren(), mutableClassObjectDescriptor.getScopeForMemberResolution(), ClassKind.ENUM_ENTRY,
600 false, JetPsiUtil.safeName(declaration.getName()));
601 context.getClasses().put(declaration, mutableClassDescriptor);
602
603 prepareForDeferredCall(mutableClassDescriptor.getScopeForMemberResolution(), mutableClassDescriptor, declaration);
604
605 // ??? - is enum entry object?
606 createPrimaryConstructorForObject(declaration, mutableClassDescriptor);
607 owner.addObjectDescriptor(mutableClassDescriptor);
608 trace.record(BindingContext.CLASS, declaration, mutableClassDescriptor);
609 return mutableClassDescriptor;
610 }
611
612 private ConstructorDescriptorImpl createPrimaryConstructorForObject(
613 @Nullable PsiElement object,
614 MutableClassDescriptor mutableClassDescriptor
615 ) {
616 ConstructorDescriptorImpl constructorDescriptor = DescriptorResolver
617 .createAndRecordPrimaryConstructorForObject(object, mutableClassDescriptor, trace);
618 mutableClassDescriptor.setPrimaryConstructor(constructorDescriptor);
619 return constructorDescriptor;
620 }
621
622 private void prepareForDeferredCall(
623 @NotNull JetScope outerScope,
624 @NotNull DeclarationDescriptor descriptorForDeferredResolve,
625 @NotNull JetDeclarationContainer container
626 ) {
627 forDeferredResolve.add(container);
628 context.normalScope.put(container, outerScope);
629 context.forDeferredResolver.put(container, descriptorForDeferredResolve);
630 }
631 }
632 }