public static void reportCyclicInheritanceHierarchyError(
      @NotNull BindingTrace trace,
      @NotNull ClassDescriptor classDescriptor,
      @NotNull ClassDescriptor superclass) {
    PsiElement psiElement =
        BindingContextUtils.classDescriptorToDeclaration(
            trace.getBindingContext(), classDescriptor);

    PsiElement elementToMark = null;
    if (psiElement instanceof JetClassOrObject) {
      JetClassOrObject classOrObject = (JetClassOrObject) psiElement;
      for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
        JetTypeReference typeReference = delegationSpecifier.getTypeReference();
        if (typeReference == null) continue;
        JetType supertype = trace.get(TYPE, typeReference);
        if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
          elementToMark = typeReference;
        }
      }
    }
    if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
      PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
      PsiElement nameIdentifier = namedElement.getNameIdentifier();
      if (nameIdentifier != null) {
        elementToMark = nameIdentifier;
      }
    }
    if (elementToMark != null) {
      trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
    }
  }
Exemple #2
0
  public static void genClassOrObject(
      @NotNull CodegenContext parentContext,
      @NotNull JetClassOrObject aClass,
      @NotNull GenerationState state,
      @Nullable MemberCodegen<?> parentCodegen) {
    ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);

    if (descriptor == null || ErrorUtils.isError(descriptor)) {
      badDescriptor(descriptor, state.getClassBuilderMode());
      return;
    }

    if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) {
      badDescriptor(descriptor, state.getClassBuilderMode());
    }

    ClassBuilder classBuilder =
        state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
    ClassContext classContext =
        parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
    new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen)
        .generate();

    if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
      ClassBuilder traitImplBuilder =
          state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile());
      ClassContext traitImplContext =
          parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state);
      new TraitImplBodyCodegen(aClass, traitImplContext, traitImplBuilder, state, parentCodegen)
          .generate();
    }
  }
Exemple #3
0
  @Nullable
  public static JetClassOrObject getOutermostClassOrObject(
      @NotNull JetClassOrObject classOrObject) {
    JetClassOrObject current = classOrObject;
    while (true) {
      PsiElement parent = current.getParent();
      assert classOrObject.getParent() != null : "Class with no parent: " + classOrObject.getText();

      if (parent instanceof PsiFile) {
        return current;
      }
      if (parent instanceof JetClassObject) {
        // current class IS the class object declaration
        parent = parent.getParent();
        assert parent instanceof JetClassBody
            : "Parent of class object is not a class body: " + parent;
      }
      if (!(parent instanceof JetClassBody)) {
        // It is a local class, no legitimate outer
        return current;
      }

      current = (JetClassOrObject) parent.getParent();
    }
  }
  private void resolveFunctionAndPropertyHeaders(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetFile, WritableScope> entry : c.getFileScopes().entrySet()) {
      JetFile file = entry.getKey();
      WritableScope fileScope = entry.getValue();
      PackageLikeBuilder packageBuilder = c.getPackageFragments().get(file).getBuilder();

      resolveFunctionAndPropertyHeaders(
          c, file.getDeclarations(), fileScope, fileScope, fileScope, packageBuilder);
    }
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getDeclaredClasses().entrySet()) {
      JetClassOrObject classOrObject = entry.getKey();
      MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();

      resolveFunctionAndPropertyHeaders(
          c,
          classOrObject.getDeclarations(),
          classDescriptor.getScopeForMemberDeclarationResolution(),
          classDescriptor.getScopeForInitializerResolution(),
          classDescriptor.getScopeForMemberDeclarationResolution(),
          classDescriptor.getBuilder());
    }

    // TODO : Extensions
  }
 @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
  @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());
  }
Exemple #7
0
 public static void deleteClass(@NotNull JetClassOrObject clazz) {
   CheckUtil.checkWritable(clazz);
   JetFile file = (JetFile) clazz.getContainingFile();
   List<JetDeclaration> declarations = file.getDeclarations();
   if (declarations.size() == 1) {
     file.delete();
   } else {
     PsiElement parent = clazz.getParent();
     CodeEditUtil.removeChild(parent.getNode(), clazz.getNode());
   }
 }
 @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);
 }
Exemple #10
0
  private void createFunctionsForDataClasses(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getDeclaredClasses().entrySet()) {
      JetClassOrObject klass = entry.getKey();
      MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();

      if (klass instanceof JetClass
          && klass.hasPrimaryConstructor()
          && KotlinBuiltIns.getInstance().isData(classDescriptor)) {
        ConstructorDescriptor constructor =
            DescriptorUtils.getConstructorOfDataClass(classDescriptor);
        createComponentFunctions(classDescriptor, constructor);
        createCopyFunction(classDescriptor, constructor);
      }
    }
  }
  private void createTypeConstructors(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getClasses().entrySet()) {
      JetClassOrObject classOrObject = entry.getKey();
      MutableClassDescriptor descriptor = (MutableClassDescriptor) entry.getValue();
      if (classOrObject instanceof JetClass) {
        descriptorResolver.resolveMutableClassDescriptor(
            (JetClass) classOrObject, descriptor, trace);
      } else if (classOrObject instanceof JetObjectDeclaration) {
        descriptor.setModality(Modality.FINAL);
        descriptor.setVisibility(
            resolveVisibilityFromModifiers(classOrObject, getDefaultClassVisibility(descriptor)));
        descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
      }

      descriptor.createTypeConstructor();

      ClassKind kind = descriptor.getKind();
      if (kind == ClassKind.ENUM_ENTRY
          || kind == ClassKind.OBJECT
          || kind == ClassKind.ENUM_CLASS) {
        MutableClassDescriptorLite classObject = descriptor.getClassObjectDescriptor();
        assert classObject != null
            : "Enum entries and named objects should have class objects: "
                + classOrObject.getText();

        JetType supertype;
        if (kind == ClassKind.ENUM_CLASS) {
          supertype = KotlinBuiltIns.getInstance().getAnyType();
        } else {
          // This is a clever hack: each enum entry and object declaration (i.e. singleton) has a
          // synthetic class object.
          // We make this class object inherit from the singleton here, thus allowing to use the
          // singleton's class object where
          // the instance of the singleton is applicable. Effectively all members of the singleton
          // would be present in its class
          // object as fake overrides, so you can access them via standard class object notation:
          // ObjectName.memberName()
          supertype = descriptor.getDefaultType();
        }
        classObject.setSupertypes(Collections.singleton(supertype));
        classObject.createTypeConstructor();
      }
    }
  }
  private void generateClassBody() {
    FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
    PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen);

    for (JetDeclaration declaration : myClass.getDeclarations()) {
      generateDeclaration(propertyCodegen, declaration, functionCodegen);
    }

    generatePrimaryConstructorProperties(propertyCodegen, myClass);
  }
  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));
        }
      }
    }
  }
 public void putToIndex(@NotNull JetDeclaration declaration) {
   if (declaration instanceof JetClassInitializer) {
     return;
   }
   allDeclarations.add(declaration);
   if (declaration instanceof JetNamedFunction) {
     JetNamedFunction namedFunction = (JetNamedFunction) declaration;
     functions.put(safeNameForLazyResolve(namedFunction), namedFunction);
   } else if (declaration instanceof JetProperty) {
     JetProperty property = (JetProperty) declaration;
     properties.put(safeNameForLazyResolve(property), property);
   } else if (declaration instanceof JetClassOrObject) {
     JetClassOrObject classOrObject = (JetClassOrObject) declaration;
     classesAndObjects.put(safeNameForLazyResolve(classOrObject.getNameAsName()), classOrObject);
   } else if (declaration instanceof JetParameter
       || declaration instanceof JetTypedef
       || declaration instanceof JetMultiDeclaration) {
     // Do nothing, just put it into allDeclarations is enough
   } else {
     throw new IllegalArgumentException("Unknown declaration: " + declaration);
   }
 }
Exemple #15
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);
      }
    }
  }
 private void resolveAnnotationsForClassOrObject(
     AnnotationResolver annotationResolver,
     JetClassOrObject jetClass,
     MutableClassDescriptor descriptor) {
   JetModifierList modifierList = jetClass.getModifierList();
   if (modifierList != null) {
     descriptor
         .getAnnotations()
         .addAll(
             annotationResolver.resolveAnnotations(
                 descriptor.getScopeForSupertypeResolution(),
                 modifierList.getAnnotationEntries()));
   }
 }
  @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);
  }
  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());
    }
  }
Exemple #19
0
 private void resolveAnonymousInitializers(
     JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) {
   if (!context.completeAnalysisNeeded(jetClassOrObject)) return;
   List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers();
   if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
     ConstructorDescriptor primaryConstructor =
         classDescriptor.getUnsubstitutedPrimaryConstructor();
     assert primaryConstructor != null;
     final JetScope scopeForInitializers = classDescriptor.getScopeForInitializers();
     for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
       expressionTypingServices.getType(
           scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, trace);
     }
   } else {
     for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
       trace.report(ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR.on(anonymousInitializer));
     }
   }
 }
 public static void processJetClassOrObject(
     final @NotNull JetClassOrObject element,
     @NotNull ReferencesSearch.SearchParameters queryParameters) {
   String className = element.getName();
   if (className != null) {
     PsiClass lightClass =
         ApplicationManager.getApplication()
             .runReadAction(
                 new Computable<PsiClass>() {
                   @Override
                   public PsiClass compute() {
                     return LightClassUtil.getPsiClass(element);
                   }
                 });
     if (lightClass != null) {
       queryParameters
           .getOptimizer()
           .searchWord(className, queryParameters.getEffectiveSearchScope(), true, lightClass);
     }
   }
 }
  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);
  }
 private void checkAnnotationClassWithBody(JetClassOrObject classOrObject) {
   if (classOrObject.getBody() != null) {
     trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody()));
   }
 }
Exemple #23
0
  private void resolveDelegationSpecifierList(
      final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) {
    if (!context.completeAnalysisNeeded(jetClass)) return;
    final ConstructorDescriptor primaryConstructor =
        descriptor.getUnsubstitutedPrimaryConstructor();
    final JetScope scopeForConstructor =
        primaryConstructor == null
            ? null
            : FunctionDescriptorUtil.getFunctionInnerScope(
                descriptor.getScopeForSupertypeResolution(), primaryConstructor, trace);
    final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow

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

          @Override
          public void visitDelegationByExpressionSpecifier(
              JetDelegatorByExpressionSpecifier specifier) {
            if (descriptor.getKind() == ClassKind.TRAIT) {
              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.TRAIT) {
                  trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
                }
              }
            }
            JetExpression delegateExpression = specifier.getDelegateExpression();
            if (delegateExpression != null) {
              JetScope scope =
                  scopeForConstructor == null
                      ? descriptor.getScopeForMemberResolution()
                      : scopeForConstructor;
              JetType type =
                  typeInferrer.getType(scope, delegateExpression, NO_EXPECTED_TYPE, trace);
              if (type != null
                  && supertype != null
                  && !JetTypeChecker.INSTANCE.isSubtypeOf(type, supertype)) {
                trace.report(TYPE_MISMATCH.on(delegateExpression, supertype, type));
              }
            }
          }

          @Override
          public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
            JetValueArgumentList valueArgumentList = call.getValueArgumentList();
            PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
            if (descriptor.getKind() == ClassKind.TRAIT) {
              trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
            }
            JetTypeReference typeReference = call.getTypeReference();
            if (typeReference == null) return;
            if (descriptor.getUnsubstitutedPrimaryConstructor() == null) {
              assert descriptor.getKind() == ClassKind.TRAIT;
              return;
            }
            OverloadResolutionResults<FunctionDescriptor> results =
                callResolver.resolveFunctionCall(
                    trace,
                    scopeForConstructor,
                    CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call),
                    NO_EXPECTED_TYPE,
                    DataFlowInfo.EMPTY);
            if (results.isSuccess()) {
              JetType supertype = results.getResultingDescriptor().getReturnType();
              recordSupertype(typeReference, supertype);
              ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
              if (classDescriptor != null) {
                if (classDescriptor.getKind() == ClassKind.TRAIT) {
                  trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark));
                }
              }
            } else {
              recordSupertype(
                  typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
            }
          }

          @Override
          public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
            JetTypeReference typeReference = specifier.getTypeReference();
            JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
            recordSupertype(typeReference, supertype);
            if (supertype == null) return;
            ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
            if (classDescriptor == null) return;
            if (descriptor.getKind() != ClassKind.TRAIT
                && classDescriptor.hasConstructors()
                && !ErrorUtils.isError(classDescriptor.getTypeConstructor())
                && classDescriptor.getKind() != ClassKind.TRAIT) {
              boolean hasConstructorWithoutParams = false;
              for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) {
                if (constructor.getValueParameters().isEmpty()) {
                  hasConstructorWithoutParams = true;
                }
              }
              if (!hasConstructorWithoutParams) {
                trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
              } else {
                trace.report(SUPERTYPE_NOT_INITIALIZED_DEFAULT.on(specifier));
              }
            }
          }

          @Override
          public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) {
            throw new IllegalStateException("This-calls should be prohibited by the parser");
          }

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

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

    Set<TypeConstructor> parentEnum = Collections.emptySet();
    if (jetClass instanceof JetEnumEntry) {
      parentEnum =
          Collections.singleton(
              ((ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration())
                  .getTypeConstructor());
    }

    checkSupertypeList(descriptor, supertypes, parentEnum);
  }
Exemple #24
0
 public static boolean isNonLiteralObject(JetClassOrObject myClass) {
   return myClass instanceof JetObjectDeclaration
       && !((JetObjectDeclaration) myClass).isObjectLiteral()
       && !(myClass.getParent() instanceof JetClassObject);
 }
Exemple #25
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);
  }