@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    LanguageLevel languageLevel = PsiUtil.getLanguageLevel(holder.getFile());
    if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) return PsiElementVisitor.EMPTY_VISITOR;
    return new JavaElementVisitor() {
      @Override
      public void visitCallExpression(@NotNull PsiCallExpression call) {
        CharsetMatch match = StreamEx.of(MATCHERS)
          .map(matcher -> matcher.extractCharsetMatch(languageLevel, call))
          .nonNull()
          .findFirst().orElse(null);
        if (match == null) return;
        addCharsetReplacement(match.myStringCharset, match.myStringCharset);
      }

      @Override
      public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
        super.visitMethodCallExpression(call);
        if (!FOR_NAME_MATCHER.matches(call)) return;
        PsiExpressionList arguments = call.getArgumentList();
        PsiExpression charset = arguments.getExpressions()[0];
        addCharsetReplacement(call, charset);
      }

      private void addCharsetReplacement(@NotNull PsiElement place, @NotNull PsiExpression charset) {
        String charsetString = getCharsetString(charset);
        if (charsetString == null) return;
        holder.registerProblem(place, JavaBundle.message("inspection.charset.object.can.be.used.message", sanitizeExpression(charsetString)),
                               new CharsetObjectCanBeUsedFix(charsetString));
      }

      @Nullable
      private static String getCharsetString(PsiExpression charsetExpression) {
        charsetExpression = PsiUtil.skipParenthesizedExprDown(charsetExpression);
        String charsetString = ObjectUtils.tryCast(ExpressionUtils.computeConstantExpression(charsetExpression), String.class);
        if (charsetString == null && charsetExpression instanceof PsiMethodCallExpression) {
          if (CHARSET_NAME.matches(charsetExpression)) {
            PsiExpression qualifier = ((PsiMethodCallExpression)charsetExpression).getMethodExpression().getQualifierExpression();
            if (qualifier != null) {
              return qualifier.getText();
            }
          }
        }
        if (charsetString == null) return null;
        charsetString = StringUtil.toUpperCase(charsetString);
        String constantName = SUPPORTED_CHARSETS.get(charsetString);
        if (constantName == null) return null;
        String finalExpression = "java.nio.charset.StandardCharsets." + constantName;
        if (charsetExpression instanceof PsiLiteralExpression) return finalExpression;
        if (charsetExpression instanceof PsiReferenceExpression) {
          String name = ((PsiReferenceExpression)charsetExpression).getReferenceName();
          if (name == null) return null;
          String baseName = StringUtil.toLowerCase(name.replaceAll("[^A-Z0-9]", ""));
          String baseCharset = StringUtil.toLowerCase(charsetString.replaceAll("[^A-Z0-9]", ""));
          // Do not report constants which name is not based on charset name (like "ENCODING", "DEFAULT_ENCODING", etc.)
          // because replacement might not be well-suitable
          if (!baseName.contains(baseCharset)) return null;
          return finalExpression;
        }
        return null;
      }
    };
  }
@NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly)