/**
   * This method tries to resolve descriptors ambiguity between class descriptor and package
   * descriptor for the same class. It's ok choose class for expression reference resolution.
   *
   * @return <code>true</code> if method has successfully resolved ambiguity
   */
  private static boolean resolveClassPackageAmbiguity(
      @NotNull Collection<DeclarationDescriptor> filteredDescriptors,
      @NotNull JetSimpleNameExpression referenceExpression,
      @NotNull JetScope resolutionScope,
      @NotNull BindingTrace trace,
      @NotNull JetScope scopeToCheckVisibility) {
    if (filteredDescriptors.size() == 2) {
      PackageViewDescriptor packageView = null;
      ClassDescriptor classDescriptor = null;

      for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) {
        if (filteredDescriptor instanceof PackageViewDescriptor) {
          packageView = (PackageViewDescriptor) filteredDescriptor;
        } else if (filteredDescriptor instanceof ClassDescriptor) {
          classDescriptor = (ClassDescriptor) filteredDescriptor;
        }
      }

      if (packageView != null && classDescriptor != null) {
        if (packageView.getFqName().equalsTo(DescriptorUtils.getFqName(classDescriptor))) {
          trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor);
          trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
          checkVisibility(classDescriptor, trace, referenceExpression, scopeToCheckVisibility);
          return true;
        }
      }
    }

    return false;
  }
Example #2
0
  public LazyClassDescriptor(
      @NotNull final LazyClassContext c,
      @NotNull DeclarationDescriptor containingDeclaration,
      @NotNull Name name,
      @NotNull final KtClassLikeInfo classLikeInfo) {
    super(
        c.getStorageManager(),
        containingDeclaration,
        name,
        KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject()));
    this.c = c;

    KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
    if (classOrObject != null) {
      this.c.getTrace().record(BindingContext.CLASS, classOrObject, this);
    }
    this.c
        .getTrace()
        .record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this);

    this.declarationProvider =
        c.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);

    StorageManager storageManager = c.getStorageManager();

    this.unsubstitutedMemberScope = createMemberScope(c, this.declarationProvider);
    this.kind = classLikeInfo.getClassKind();
    this.staticScope =
        kind == ClassKind.ENUM_CLASS
            ? new StaticScopeForKotlinEnum(storageManager, this)
            : MemberScope.Empty.INSTANCE;

    this.typeConstructor = new LazyClassTypeConstructor();

    this.isCompanionObject =
        classLikeInfo instanceof KtObjectInfo && ((KtObjectInfo) classLikeInfo).isCompanionObject();

    KtModifierList modifierList = classLikeInfo.getModifierList();
    if (kind.isSingleton()) {
      this.modality = Modality.FINAL;
    } else {
      Modality defaultModality = kind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL;
      this.modality =
          resolveModalityFromModifiers(modifierList, defaultModality, /* allowSealed = */ true);
    }

    boolean isLocal = classOrObject != null && KtPsiUtil.isLocal(classOrObject);
    Visibility defaultVisibility;
    if (kind == ClassKind.ENUM_ENTRY || (kind == ClassKind.OBJECT && isCompanionObject)) {
      defaultVisibility = Visibilities.PUBLIC;
    } else {
      defaultVisibility = Visibilities.DEFAULT_VISIBILITY;
    }
    this.visibility =
        isLocal
            ? Visibilities.LOCAL
            : resolveVisibilityFromModifiers(modifierList, defaultVisibility);

    this.isInner = isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(this);
    this.isData = modifierList != null && modifierList.hasModifier(KtTokens.DATA_KEYWORD);

    // Annotation entries are taken from both own annotations (if any) and object literal
    // annotations (if any)
    List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
    if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
      // TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
      annotationEntries.addAll(
          KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
    }
    if (modifierList != null) {
      annotationEntries.addAll(modifierList.getAnnotationEntries());
    }
    if (!annotationEntries.isEmpty()) {
      this.annotations =
          new LazyAnnotations(
              new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) {
                @NotNull
                @Override
                public LexicalScope getScope() {
                  return getOuterScope();
                }
              },
              annotationEntries);
    } else {
      this.annotations = Annotations.Companion.getEMPTY();
    }

    List<KtAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations();
    if (jetDanglingAnnotations.isEmpty()) {
      this.danglingAnnotations = Annotations.Companion.getEMPTY();
    } else {
      this.danglingAnnotations =
          new LazyAnnotations(
              new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) {
                @NotNull
                @Override
                public LexicalScope getScope() {
                  return getScopeForMemberDeclarationResolution();
                }
              },
              jetDanglingAnnotations);
    }

    this.companionObjectDescriptor =
        storageManager.createNullableLazyValue(
            new Function0<LazyClassDescriptor>() {
              @Override
              public LazyClassDescriptor invoke() {
                return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed());
              }
            });
    this.extraCompanionObjectDescriptors =
        storageManager.createMemoizedFunction(
            new Function1<KtObjectDeclaration, ClassDescriptor>() {
              @Override
              public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
                return computeCompanionObjectDescriptor(companionObject);
              }
            });
    this.forceResolveAllContents =
        storageManager.createRecursionTolerantNullableLazyValue(
            new Function0<Void>() {
              @Override
              public Void invoke() {
                doForceResolveAllContents();
                return null;
              }
            },
            null);

    this.resolutionScopesSupport =
        new ClassResolutionScopesSupport(
            this,
            storageManager,
            new Function0<LexicalScope>() {
              @Override
              public LexicalScope invoke() {
                return getOuterScope();
              }
            });

    this.parameters =
        c.getStorageManager()
            .createLazyValue(
                new Function0<List<TypeParameterDescriptor>>() {
                  @Override
                  public List<TypeParameterDescriptor> invoke() {
                    KtClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
                    KtTypeParameterList typeParameterList = classInfo.getTypeParameterList();
                    if (typeParameterList == null) return Collections.emptyList();

                    if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) {
                      c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList));
                    }

                    List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
                    if (typeParameters.isEmpty()) return Collections.emptyList();

                    List<TypeParameterDescriptor> parameters =
                        new ArrayList<TypeParameterDescriptor>(typeParameters.size());

                    for (int i = 0; i < typeParameters.size(); i++) {
                      parameters.add(
                          new LazyTypeParameterDescriptor(
                              c, LazyClassDescriptor.this, typeParameters.get(i), i));
                    }

                    return parameters;
                  }
                });

    this.scopeForInitializerResolution =
        storageManager.createLazyValue(
            new Function0<LexicalScope>() {
              @Override
              public LexicalScope invoke() {
                return ClassResolutionScopesSupportKt.scopeForInitializerResolution(
                    LazyClassDescriptor.this,
                    createInitializerScopeParent(),
                    classLikeInfo.getPrimaryConstructorParameters());
              }
            });
  }