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