private EnumEnding getEndingOfLastEnumConstantIfRemoved()

in legacy/java/piranha/src/main/java/com/uber/piranha/XPFlagCleaner.java [1086:1153]


  private EnumEnding getEndingOfLastEnumConstantIfRemoved(Symbol enumSym, VisitorState state) {
    ClassTree enumClassTree = ASTHelpers.findClass(enumSym.enclClass(), state);

    if (enumClassTree == null) {
      return EnumEnding.IGNORE;
    }

    // Find enum initializer members only
    List<VariableTree> enumConstants = getEnumConstants(enumClassTree).collect(Collectors.toList());

    // Get second to last index
    //
    // The reason to get the second to last index, is that we need to alter the second to last enum
    // constant ending if the last constant is being removed, as the second to last enum constant
    // will now become the last constant.
    //
    // In Java, the last enum constant is be required to have a different ending than other enum
    // constants in the enum if the enum has non-enum constant members
    //
    // We do not need to alter any other enum constants because they will either never become the
    // last constant [0 ... size - 3] or will be removed [size - 1].
    int index = enumConstants.size() - 2;

    // Check if the second to last enum is the current enum being processed
    if (index < 0 || !enumConstants.get(index).getName().equals(enumSym.getSimpleName())) {
      return EnumEnding.IGNORE;
    }

    VariableTree nextConstant = enumConstants.get(index + 1);
    String nextEnumConstantSource = state.getSourceForNode(nextConstant);
    // The enclosingEnumSource is the source code of the enum that will contain both the current
    // enum constant and the next enum constant
    String enclosingEnumSource = state.getSourceForNode(state.getPath().getParentPath().getLeaf());

    // We need access to the source to remove the enum constant in the first place
    if (nextEnumConstantSource == null || enclosingEnumSource == null) {
      return EnumEnding.IGNORE;
    }

    // Make sure the last enum constant in the member list will actually be removed and cleaned up
    // If not, we don't want to alter the prior enum constant
    //
    // These are the same checks that would run from the point in the AST were we at the enum
    // constant that is being removed instead of the enum constant right before. We're skipping
    // around the tree a bit here.
    //
    // The reason for re-checking if we are going to clean up the last enum constant when we
    // encounter the second to last enum constant, rather than doing the check when we encounter the
    // last enum constant, is because we are altering the syntax of the second to last enum
    // constant. It is easier to add a SuggestedFix with the design of error-prone's BugChecker at
    // the time you encounter that piece of code you are altering, than to attempt to add a fix
    // outside of encountering that piece of code in the syntax tree traversal.
    if (!(xpFlagName.equals(nextConstant.getName().toString())
        || isEnumConstantMatchingFlagName(
            nextConstant.getName().toString(), enumSym.enclClass(), state))) {
      return EnumEnding.IGNORE;
    }

    String varAsStrWithComma = nextEnumConstantSource + ",";
    String varAsStrWithSemicolon = nextEnumConstantSource + ";";
    if (enclosingEnumSource.contains(varAsStrWithComma)) {
      return EnumEnding.COMMA;
    } else if (enclosingEnumSource.contains(varAsStrWithSemicolon)) {
      return EnumEnding.SEMICOLON;
    } else {
      return EnumEnding.NONE;
    }
  }