예제 #1
0
 public static boolean enumEntryAfterEnumMember(@NotNull JetEnumEntry enumEntry) {
   PsiElement previous = enumEntry.getPrevSibling();
   while (previous != null) {
     if (previous instanceof JetEnumEntry) return false;
     if (previous instanceof JetDeclaration) return true;
     previous = previous.getPrevSibling();
   }
   return false;
 }
예제 #2
0
    @Override
    public void visitEnumEntry(@NotNull JetEnumEntry declaration) {
      MutableClassDescriptor descriptor =
          createClassDescriptorForSingleton(
              declaration, JetPsiUtil.safeName(declaration.getName()), ClassKind.ENUM_ENTRY);

      owner.addClassifierDescriptor(descriptor);

      descriptor.getBuilder().setClassObjectDescriptor(createSyntheticClassObject(descriptor));
    }
예제 #3
0
 // Temporary
 // Returns true if deprecated constructor is in use, like
 // ENTRY: Enum(arguments) instead of
 // ENTRY(arguments)
 public static boolean enumEntryUsesDeprecatedSuperConstructor(@NotNull JetEnumEntry enumEntry) {
   JetInitializerList initializerList = enumEntry.getInitializerList();
   if (initializerList == null || initializerList.getInitializers().isEmpty()) return false;
   JetTypeReference typeReference = initializerList.getInitializers().get(0).getTypeReference();
   if (typeReference == null) return false;
   JetUserType userType = (JetUserType) typeReference.getTypeElement();
   if (userType == null
       || userType.getReferenceExpression() instanceof JetEnumEntrySuperclassReferenceExpression)
     return false;
   return true;
 }
예제 #4
0
  private void checkEnumEntry(
      @NotNull JetEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) {
    DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration();
    assert DescriptorUtils.isEnumClass(declaration)
        : "Enum entry should be declared in enum class: " + classDescriptor;
    ClassDescriptor enumClass = (ClassDescriptor) declaration;

    if (enumEntryUsesDeprecatedSuperConstructor(enumEntry)) {
      trace.report(
          Errors.ENUM_ENTRY_USES_DEPRECATED_SUPER_CONSTRUCTOR.on(enumEntry, classDescriptor));
    }
    String neededDelimiter = enumEntryExpectedDelimiter(enumEntry);
    if (!neededDelimiter.isEmpty()) {
      trace.report(
          Errors.ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER.on(
              enumEntry, classDescriptor, neededDelimiter));
    }
    if (enumEntryAfterEnumMember(enumEntry)) {
      trace.report(Errors.ENUM_ENTRY_AFTER_ENUM_MEMBER.on(enumEntry, classDescriptor));
    }

    List<JetDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers();
    ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor();
    if ((constructor == null || !constructor.getValueParameters().isEmpty())
        && delegationSpecifiers.isEmpty()) {
      trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry, enumClass));
    }

    for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) {
      JetTypeReference typeReference = delegationSpecifier.getTypeReference();
      if (typeReference != null) {
        JetType type = trace.getBindingContext().get(TYPE, typeReference);
        if (type != null) {
          JetType enumType = enumClass.getDefaultType();
          if (!type.getConstructor().equals(enumType.getConstructor())) {
            trace.report(ENUM_ENTRY_ILLEGAL_TYPE.on(typeReference, enumClass));
          }
        }
      }
    }
  }
예제 #5
0
 // Temporary
 // Returns comma if it's an enum entry without following comma (entry is not last in enum),
 // or semicolon if it's an enum entry without following semicolon, may be after comma (entry is
 // last in enum),
 // or empty string if an enum entry has the necessary following delimiter
 @NotNull
 private static String enumEntryExpectedDelimiter(@NotNull JetEnumEntry enumEntry) {
   PsiElement next = enumEntry.getNextSibling();
   while (next != null) {
     if (next instanceof JetDeclaration) break;
     next = next.getNextSibling();
   }
   JetDeclaration nextDeclaration = (JetDeclaration) next;
   next = PsiUtilPackage.getNextSiblingIgnoringWhitespaceAndComments(enumEntry);
   IElementType nextType = next != null ? next.getNode().getElementType() : null;
   if (nextDeclaration instanceof JetEnumEntry) {
     // Not last
     return nextType != JetTokens.COMMA ? "," : "";
   } else {
     // Last: after it we can have semicolon, just closing brace, or comma followed by semicolon /
     // closing brace
     if (nextType == JetTokens.COMMA) {
       next = PsiUtilPackage.getNextSiblingIgnoringWhitespaceAndComments(next);
       nextType = next != null ? next.getNode().getElementType() : null;
     }
     return nextType != JetTokens.SEMICOLON && nextType != JetTokens.RBRACE ? ";" : "";
   }
 }