@NotNull
  @Override
  public LightClassConstructionContext getContextForClassOrObject(
      @NotNull JetClassOrObject classOrObject) {
    ResolveSessionForBodies session =
        KotlinCacheService.getInstance(classOrObject.getProject())
            .getLazyResolveSession(classOrObject);

    if (classOrObject.isLocal()) {
      BindingContext bindingContext = session.resolveToElement(classOrObject, BodyResolveMode.FULL);
      ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classOrObject);

      if (descriptor == null) {
        LOG.warn(
            "No class descriptor in context for class: "
                + PsiUtilPackage.getElementTextWithContext(classOrObject));
        return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor());
      }

      ForceResolveUtil.forceResolveAllContents(descriptor);

      return new LightClassConstructionContext(bindingContext, session.getModuleDescriptor());
    }

    ForceResolveUtil.forceResolveAllContents(session.getClassDescriptor(classOrObject));
    return new LightClassConstructionContext(
        session.getBindingContext(), session.getModuleDescriptor());
  }
 @NotNull
 private static PsiClass findCorrespondingLightClass(
     @NotNull JetClassOrObject decompiledClassOrObject,
     @NotNull PsiClass rootLightClassForDecompiledFile) {
   FqName relativeFqName = getClassRelativeName(decompiledClassOrObject);
   Iterator<Name> iterator = relativeFqName.pathSegments().iterator();
   Name base = iterator.next();
   assert rootLightClassForDecompiledFile.getName().equals(base.asString())
       : "Light class for file:\n"
           + decompiledClassOrObject.getContainingJetFile().getVirtualFile().getCanonicalPath()
           + "\nwas expected to have name: "
           + base.asString()
           + "\n Actual: "
           + rootLightClassForDecompiledFile.getName();
   PsiClass current = rootLightClassForDecompiledFile;
   while (iterator.hasNext()) {
     Name name = iterator.next();
     PsiClass innerClass = current.findInnerClassByName(name.asString(), false);
     assert innerClass != null
         : "Could not find corresponding inner/nested class "
             + relativeFqName
             + " in class "
             + decompiledClassOrObject.getFqName()
             + "\n"
             + "File: "
             + decompiledClassOrObject.getContainingJetFile().getVirtualFile().getName();
     current = innerClass;
   }
   return current;
 }
 @NotNull
 private static FqName getClassRelativeName(@NotNull JetClassOrObject decompiledClassOrObject) {
   Name name = decompiledClassOrObject.getNameAsName();
   assert name != null;
   JetClassOrObject parent =
       PsiTreeUtil.getParentOfType(decompiledClassOrObject, JetClassOrObject.class, true);
   if (parent == null) {
     assert decompiledClassOrObject.isTopLevel();
     return FqName.topLevel(name);
   }
   return getClassRelativeName(parent).child(name);
 }
 @Nullable
 @Override
 public PsiClass getPsiClass(@NotNull JetClassOrObject classOrObject) {
   VirtualFile virtualFile = classOrObject.getContainingFile().getVirtualFile();
   if (virtualFile != null
       && LibraryUtil.findLibraryEntry(virtualFile, classOrObject.getProject()) != null) {
     if (ProjectRootsUtil.isLibraryClassFile(project, virtualFile)) {
       return getLightClassForDecompiledClassOrObject(classOrObject);
     }
     return JetSourceNavigationHelper.getOriginalClass(classOrObject);
   }
   return KotlinLightClassForExplicitDeclaration.create(psiManager, classOrObject);
 }
 @NotNull
 private List<JetParameter> getPrimaryConstructorParameters() {
   if (declaration instanceof JetClass) {
     return declaration.getPrimaryConstructorParameters();
   }
   return Collections.emptyList();
 }
Esempio n. 6
0
  private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) {
    Multimap<TypeConstructor, TypeProjection> multimap =
        SubstitutionUtils.buildDeepSubstitutionMultimap(classDescriptor.getDefaultType());
    for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry :
        multimap.asMap().entrySet()) {
      Collection<TypeProjection> projections = entry.getValue();
      if (projections.size() > 1) {
        TypeConstructor typeConstructor = entry.getKey();
        DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
        assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
        TypeParameterDescriptor typeParameterDescriptor =
            (TypeParameterDescriptor) declarationDescriptor;

        // Immediate arguments of supertypes cannot be projected
        Set<JetType> conflictingTypes = Sets.newLinkedHashSet();
        for (TypeProjection projection : projections) {
          conflictingTypes.add(projection.getType());
        }
        removeDuplicateTypes(conflictingTypes);
        if (conflictingTypes.size() > 1) {
          DeclarationDescriptor containingDeclaration =
              typeParameterDescriptor.getContainingDeclaration();
          assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
          JetClassOrObject psiElement =
              (JetClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);
          assert psiElement != null;
          JetDelegationSpecifierList delegationSpecifierList =
              psiElement.getDelegationSpecifierList();
          assert delegationSpecifierList != null;
          //
          // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter
          // " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + "
          // has inconsistent values: " + conflictingTypes);
          trace.report(
              INCONSISTENT_TYPE_PARAMETER_VALUES.on(
                  delegationSpecifierList,
                  typeParameterDescriptor,
                  (ClassDescriptor) containingDeclaration,
                  conflictingTypes));
        }
      }
    }
  }
Esempio n. 7
0
  private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getDeclaredClasses().entrySet()) {
      JetClassOrObject klass = entry.getKey();
      ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
      ConstructorDescriptor unsubstitutedPrimaryConstructor =
          classDescriptor.getUnsubstitutedPrimaryConstructor();
      if (unsubstitutedPrimaryConstructor != null) {
        ForceResolveUtil.forceResolveAllContents(unsubstitutedPrimaryConstructor.getAnnotations());

        LexicalScope parameterScope =
            getPrimaryConstructorParametersScope(
                classDescriptor.getScopeForClassHeaderResolution(),
                unsubstitutedPrimaryConstructor);
        valueParameterResolver.resolveValueParameters(
            klass.getPrimaryConstructorParameters(),
            unsubstitutedPrimaryConstructor.getValueParameters(),
            parameterScope,
            c.getOuterDataFlowInfo(),
            trace);
      }
    }
  }
  @Nullable
  private static PsiClass getLightClassForDecompiledClassOrObject(
      @NotNull JetClassOrObject decompiledClassOrObject) {
    if (decompiledClassOrObject instanceof JetEnumEntry) {
      return null;
    }
    JetFile containingJetFile = decompiledClassOrObject.getContainingJetFile();
    if (!containingJetFile.isCompiled()) {
      return null;
    }
    PsiClass rootLightClassForDecompiledFile =
        createLightClassForDecompiledKotlinFile(containingJetFile);
    if (rootLightClassForDecompiledFile == null) return null;

    return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile);
  }
Esempio n. 9
0
  private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) {
    for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
      checkBoundsForTypeInClassHeader(delegationSpecifier.getTypeReference());
    }

    if (!(classOrObject instanceof JetClass)) return;
    JetClass jetClass = (JetClass) classOrObject;

    for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
      checkBoundsForTypeInClassHeader(jetTypeParameter.getExtendsBound());
      checkFinalUpperBounds(jetTypeParameter.getExtendsBound());
    }

    for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) {
      checkBoundsForTypeInClassHeader(constraint.getBoundTypeReference());
      checkFinalUpperBounds(constraint.getBoundTypeReference());
    }
  }
Esempio n. 10
0
  private void checkPrimaryConstructor(
      JetClassOrObject classOrObject, ClassDescriptor classDescriptor) {
    ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
    JetPrimaryConstructor declaration = classOrObject.getPrimaryConstructor();
    if (primaryConstructor == null || declaration == null) return;

    for (JetParameter parameter : declaration.getValueParameters()) {
      PropertyDescriptor propertyDescriptor =
          trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
      if (propertyDescriptor != null) {
        modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor);
      }
    }

    if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) {
      trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList()));
    }

    if (!(classOrObject instanceof JetClass)) {
      trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration));
    }

    checkConstructorDeclaration(primaryConstructor, declaration);
  }
Esempio n. 11
0
 private void checkAnnotationClassWithBody(JetClassOrObject classOrObject) {
   if (classOrObject.getBody() != null) {
     trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody()));
   }
 }
Esempio n. 12
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);
  }