public Description matchMethod()

in legacy/java/piranha/src/main/java/com/uber/piranha/XPFlagCleaner.java [1284:1357]


  public Description matchMethod(MethodTree tree, VisitorState state) {
    if (shouldSkip(state)) return Description.NO_MATCH;

    boolean deleteMethod = false;
    List<AnnotationTree> deletableAnnotations = new ArrayList<>();
    // Deletable identifiers used as part of the argument to an annotation, for when the entire
    // annotation doesn't need to be deleted
    List<ExpressionTree> deletableIdentifiers = new ArrayList<>();
    final ImmutableSet<ResolvedTestAnnotation> resolvedTestAnnotations =
        config.resolveTestAnnotations(tree, state);
    if (resolvedTestAnnotations.size() != 0) {
      // If there are any test annotations for this method, then we clean up based on those. We do
      // this even if
      // the method is not otherwise a recognized test method (e.g. marked @Test) and we ignore all
      // other
      // applicable clean up heuristics
      for (ResolvedTestAnnotation resolved : resolvedTestAnnotations) {
        Set<AnnotationArgument> matchedFlagsWorkingSet = new HashSet<>();
        for (AnnotationArgument testedFlag : resolved.getFlags()) {
          if (testedFlag.getValue().equals(xpFlagName)) {
            if (isTreated == resolved.isTreated()) {
              // Annotation requests the same treatment state as what Piranha is setting the flag to
              matchedFlagsWorkingSet.add(testedFlag);
            } else {
              // Annotation (and therefore test method) requests a different (now impossible)
              // treatment, compared to what Piranha is setting the flag to.
              deleteMethod = true;
            }
          }
        }
        // Should we delete the full annotation, or specific flags within it? Depends if all
        // flags mentioned within the annotation have been matched or not:
        if (matchedFlagsWorkingSet.size() == resolved.getFlags().size()) {
          deletableAnnotations.add(resolved.getSourceTree());
        } else {
          // Only remove the matched flag references, but preserve the annotation and its
          // references to remaining flags
          matchedFlagsWorkingSet.forEach(arg -> deletableIdentifiers.add(arg.getSourceTree()));
        }
        matchedFlagsWorkingSet.clear();
      }
    } else if (config.shouldCleanTestMethodsByContent()
        && PiranhaUtils.isUnitTestMethod(tree, state)) {
      deleteMethod = shouldCleanBySetters(tree, state);
    }
    // Early exit for no changes required:
    if (!deleteMethod && deletableAnnotations.size() == 0 && deletableIdentifiers.size() == 0) {
      return Description.NO_MATCH;
    }
    // Process refactoring
    Description.Builder builder = buildDescription(tree);
    SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
    // Check first if the whole method must go away
    if (deleteMethod) {
      fixBuilder.delete(tree);
      decrementAllSymbolUsages(tree, state, fixBuilder);
      skipWithin(state.getPath()); // Deleting full method, skip refactorings within it
    } else {
      // Otherwise, we might still need to clean up individual obsolete test annotations and flag
      // references within multi-flag annotations.
      // Note that the AST elements referenced by deletableAnnotations and deletableIdentifiers
      // should not overlap, given the logic above, so deleting each independently is safe.
      for (ExpressionTree expr : deletableIdentifiers) {
        fixBuilder = deleteExprWithComma(state, expr, resolvedTestAnnotations, fixBuilder);
        decrementAllSymbolUsages(expr, state, fixBuilder);
      }
      for (AnnotationTree at : deletableAnnotations) {
        fixBuilder.delete(at);
        decrementAllSymbolUsages(at, state, fixBuilder);
      }
    }
    builder.addFix(fixBuilder.build());
    return builder.build();
  }