Ejemplo n.º 1
0
  // Note: headers of member classes' members are not resolved
  public void resolveMemberHeaders() {
    ForceResolveUtil.forceResolveAllContents(getAnnotations());
    ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());

    getCompanionObjectDescriptor();

    getDescriptorsForExtraCompanionObjects();

    getConstructors();
    getContainingDeclaration();
    getThisAsReceiverParameter();
    getKind();
    getModality();
    getName();
    getOriginal();
    getScopeForClassHeaderResolution();
    getScopeForMemberDeclarationResolution();
    DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope());
    getScopeForInitializerResolution();
    getUnsubstitutedInnerClassesScope();
    getTypeConstructor().getSupertypes();
    for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
      typeParameterDescriptor.getUpperBounds();
    }
    getUnsubstitutedPrimaryConstructor();
    getVisibility();
  }
Ejemplo n.º 2
0
  /**
   * 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;
  }
Ejemplo n.º 3
0
  @NotNull
  public static Pair<FunctionDescriptor, PsiElement> getContainingFunctionSkipFunctionLiterals(
      @Nullable DeclarationDescriptor startDescriptor, boolean strict) {
    FunctionDescriptor containingFunctionDescriptor =
        DescriptorUtils.getParentOfType(startDescriptor, FunctionDescriptor.class, strict);
    PsiElement containingFunction =
        containingFunctionDescriptor != null
            ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor)
            : null;
    while (containingFunction instanceof JetFunctionLiteral) {
      containingFunctionDescriptor =
          DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class);
      containingFunction =
          containingFunctionDescriptor != null
              ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor)
              : null;
    }

    return new Pair<FunctionDescriptor, PsiElement>(
        containingFunctionDescriptor, containingFunction);
  }
Ejemplo n.º 4
0
  @NotNull
  private static InnerModifierCheckResult checkIllegalInner(
      @NotNull DeclarationDescriptor descriptor) {
    if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION;
    ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;

    if (classDescriptor.getKind() != ClassKind.CLASS)
      return InnerModifierCheckResult.ILLEGAL_POSITION;

    DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration();
    if (!(containingDeclaration instanceof ClassDescriptor))
      return InnerModifierCheckResult.ILLEGAL_POSITION;

    if (DescriptorUtils.isTrait(containingDeclaration)) {
      return InnerModifierCheckResult.IN_TRAIT;
    } else if (DescriptorUtils.isObject(containingDeclaration)) {
      return InnerModifierCheckResult.IN_OBJECT;
    } else {
      return InnerModifierCheckResult.ALLOWED;
    }
  }
Ejemplo n.º 5
0
 @NotNull
 @Override
 public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
   //noinspection unchecked
   return (Collection)
       CollectionsKt.filter(
           DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope),
           new Function1<DeclarationDescriptor, Boolean>() {
             @Override
             public Boolean invoke(DeclarationDescriptor descriptor) {
               return descriptor instanceof CallableMemberDescriptor
                   && ((CallableMemberDescriptor) descriptor).getKind()
                       != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
             }
           });
 }
Ejemplo n.º 6
0
 @Nullable
 private LazyClassDescriptor computeCompanionObjectDescriptor(
     @Nullable KtObjectDeclaration companionObject) {
   KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
   if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
     return null;
   }
   Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName();
   assert name != null;
   getUnsubstitutedMemberScope()
       .getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
   ClassDescriptor companionObjectDescriptor =
       c.getTrace().get(BindingContext.CLASS, companionObject);
   if (companionObjectDescriptor instanceof LazyClassDescriptor) {
     assert DescriptorUtils.isCompanionObject(companionObjectDescriptor)
         : "Not a companion object: " + companionObjectDescriptor;
     return (LazyClassDescriptor) companionObjectDescriptor;
   } else {
     return null;
   }
 }
Ejemplo n.º 7
0
  /** @return whether f overrides g */
  public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
    // In a multi-module project different "copies" of the same class may be present in different
    // libraries,
    // that's why we use structural equivalence for members (DescriptorEquivalenceForOverrides).

    // This first check cover the case of duplicate classes in different modules:
    // when B is defined in modules m1 and m2, and C (indirectly) inherits from both versions,
    // we'll be getting sets of members that do not override each other, but are structurally
    // equivalent.
    // As other code relies on no equal descriptors passed here, we guard against f == g, but this
    // may not be necessary
    // Note that this is needed for the usage of this function in the IDE code
    if (!f.equals(g)
        && DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(
            f.getOriginal(), g.getOriginal())) return true;

    CallableDescriptor originalG = g.getOriginal();
    for (D overriddenFunction : DescriptorUtils.getAllOverriddenDescriptors(f)) {
      if (DescriptorEquivalenceForOverrides.INSTANCE.areEquivalent(originalG, overriddenFunction))
        return true;
    }
    return false;
  }
Ejemplo n.º 8
0
 private boolean isCompanionObjectAllowed() {
   return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this));
 }
Ejemplo n.º 9
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());
              }
            });
  }
Ejemplo n.º 10
0
  private void checkSupertypeList(
      @NotNull ClassDescriptor supertypeOwner,
      @NotNull Map<JetTypeReference, JetType> supertypes,
      @NotNull JetClassOrObject jetClass) {
    Set<TypeConstructor> allowedFinalSupertypes =
        getAllowedFinalSupertypes(supertypeOwner, jetClass);
    Set<TypeConstructor> typeConstructors = Sets.newHashSet();
    boolean classAppeared = false;
    for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
      JetTypeReference typeReference = entry.getKey();
      JetType supertype = entry.getValue();

      boolean addSupertype = true;

      ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
      if (classDescriptor != null) {
        if (ErrorUtils.isError(classDescriptor)) continue;

        if (classDescriptor.getKind() != ClassKind.INTERFACE) {
          if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
            trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
            addSupertype = false;
          } else if (supertypeOwner.getKind() == ClassKind.INTERFACE
              && !classAppeared
              && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) {
            trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference));
            addSupertype = false;
          }

          if (classAppeared) {
            trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
          } else {
            classAppeared = true;
          }
        }
      } else {
        trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
      }

      TypeConstructor constructor = supertype.getConstructor();
      if (addSupertype && !typeConstructors.add(constructor)) {
        trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
      }

      if (DescriptorUtils.isSingleton(classDescriptor)) {
        trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference));
      } else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) {
        if (classDescriptor.getModality() == Modality.SEALED) {
          DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration();
          while (containingDescriptor != null && containingDescriptor != classDescriptor) {
            containingDescriptor = containingDescriptor.getContainingDeclaration();
          }
          if (containingDescriptor == null) {
            trace.report(SEALED_SUPERTYPE.on(typeReference));
          } else {
            trace.report(SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(typeReference));
          }
        } else {
          trace.report(FINAL_SUPERTYPE.on(typeReference));
        }
      }
    }
  }
Ejemplo n.º 11
0
  public void resolveDelegationSpecifierList(
      @NotNull final DataFlowInfo outerDataFlowInfo,
      @NotNull JetClassOrObject jetClass,
      @NotNull final ClassDescriptor descriptor,
      @Nullable final ConstructorDescriptor primaryConstructor,
      @NotNull LexicalScope scopeForSupertypeResolution,
      @NotNull final LexicalScope scopeForMemberResolution) {
    final LexicalScope scopeForConstructor =
        primaryConstructor == null
            ? null
            : FunctionDescriptorUtil.getFunctionInnerScope(
                scopeForSupertypeResolution, primaryConstructor, trace);
    final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow

    final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
    final ResolvedCall<?>[] primaryConstructorDelegationCall = new ResolvedCall[1];
    JetVisitorVoid visitor =
        new JetVisitorVoid() {
          private void recordSupertype(JetTypeReference typeReference, JetType supertype) {
            if (supertype == null) return;
            supertypes.put(typeReference, supertype);
          }

          @Override
          public void visitDelegationByExpressionSpecifier(
              @NotNull JetDelegatorByExpressionSpecifier specifier) {
            if (descriptor.getKind() == ClassKind.INTERFACE) {
              trace.report(DELEGATION_IN_TRAIT.on(specifier));
            }
            JetType supertype =
                trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
            recordSupertype(specifier.getTypeReference(), supertype);
            if (supertype != null) {
              DeclarationDescriptor declarationDescriptor =
                  supertype.getConstructor().getDeclarationDescriptor();
              if (declarationDescriptor instanceof ClassDescriptor) {
                ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
                if (classDescriptor.getKind() != ClassKind.INTERFACE) {
                  trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
                }
              }
            }
            JetExpression delegateExpression = specifier.getDelegateExpression();
            if (delegateExpression != null) {
              LexicalScope scope =
                  scopeForConstructor == null ? scopeForMemberResolution : scopeForConstructor;
              JetType expectedType = supertype != null ? supertype : NO_EXPECTED_TYPE;
              typeInferrer.getType(
                  scope, delegateExpression, expectedType, outerDataFlowInfo, trace);
            }
            if (primaryConstructor == null) {
              trace.report(
                  UNSUPPORTED.on(
                      specifier, "Delegation without primary constructor is not supported"));
            }
          }

          @Override
          public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
            JetValueArgumentList valueArgumentList = call.getValueArgumentList();
            PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
            if (descriptor.getKind() == ClassKind.INTERFACE) {
              trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
            }
            JetTypeReference typeReference = call.getTypeReference();
            if (typeReference == null) return;
            if (primaryConstructor == null) {
              if (descriptor.getKind() != ClassKind.INTERFACE) {
                trace.report(SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(call));
              }
              recordSupertype(
                  typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
              return;
            }
            OverloadResolutionResults<FunctionDescriptor> results =
                callResolver.resolveFunctionCall(
                    trace,
                    scopeForConstructor,
                    CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
                    NO_EXPECTED_TYPE,
                    outerDataFlowInfo,
                    false);
            if (results.isSuccess()) {
              JetType supertype = results.getResultingDescriptor().getReturnType();
              recordSupertype(typeReference, supertype);
              ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
              if (classDescriptor != null) {
                // allow only one delegating constructor
                if (primaryConstructorDelegationCall[0] == null) {
                  primaryConstructorDelegationCall[0] = results.getResultingCall();
                } else {
                  primaryConstructorDelegationCall[0] = null;
                }
              }
              // Recording type info for callee to use later in JetObjectLiteralExpression
              trace.record(PROCESSED, call.getCalleeExpression(), true);
              trace.record(
                  EXPRESSION_TYPE_INFO,
                  call.getCalleeExpression(),
                  TypeInfoFactoryPackage.noTypeInfo(
                      results.getResultingCall().getDataFlowInfoForArguments().getResultInfo()));
            } else {
              recordSupertype(
                  typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
            }
          }

          @Override
          public void visitDelegationToSuperClassSpecifier(
              @NotNull JetDelegatorToSuperClass specifier) {
            JetTypeReference typeReference = specifier.getTypeReference();
            JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
            recordSupertype(typeReference, supertype);
            if (supertype == null) return;
            ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype);
            if (superClass == null) return;
            if (superClass.getKind().isSingleton()) {
              // A "singleton in supertype" diagnostic will be reported later
              return;
            }
            if (descriptor.getKind() != ClassKind.INTERFACE
                && descriptor.getUnsubstitutedPrimaryConstructor() != null
                && superClass.getKind() != ClassKind.INTERFACE
                && !superClass.getConstructors().isEmpty()
                && !ErrorUtils.isError(superClass)) {
              trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
            }
          }

          @Override
          public void visitJetElement(@NotNull JetElement element) {
            throw new UnsupportedOperationException(element.getText() + " : " + element);
          }
        };

    for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
      delegationSpecifier.accept(visitor);
    }

    if (DescriptorUtils.isAnnotationClass(descriptor)
        && jetClass.getDelegationSpecifierList() != null) {
      trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(jetClass.getDelegationSpecifierList()));
    }

    if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) {
      recordConstructorDelegationCall(
          trace, primaryConstructor, primaryConstructorDelegationCall[0]);
    }

    checkSupertypeList(descriptor, supertypes, jetClass);
  }