// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.lang.jvm.inspection;

import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.jvm.JvmElement;
import com.intellij.lang.jvm.JvmElementVisitor;
import com.intellij.lang.jvm.source.JvmDeclarationSearch;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public abstract class JvmLocalInspection extends LocalInspectionTool {

  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    return new PsiElementVisitor() {
      @Override
      public void visitElement(PsiElement element) {
        JvmElementVisitor<Boolean> visitor = null;
        for (JvmElement jvmElement : JvmDeclarationSearch.getElementsByIdentifier(element)) {
          if (visitor == null) {
            // don't build visitor until there is at least one JvmElement
            visitor = buildJvmVisitor(
              holder.getProject(),
              (message, highlightType) -> holder.registerProblem(element, message, highlightType)
            );
            if (visitor == null) return;
          }
          Boolean result = jvmElement.accept(visitor);
          if (result == Boolean.TRUE) {
            return;
          }
        }
      }
    };
  }

  protected interface HighlightSink {

    default void highlight(@Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String message) {
      highlight(message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
    }

    void highlight(@Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String message,
                   @NotNull ProblemHighlightType highlightType);
  }

  @Nullable
  protected abstract JvmElementVisitor<Boolean> buildJvmVisitor(@NotNull Project project, @NotNull HighlightSink message);
}

@@ -233,16 +233,66 @@
 onTool;%0A
+import com.intellij.codeInspection.LocalQuickFix;%0A
 import c
@@ -658,24 +658,81 @@
 entVisitor;%0A
+import org.jetbrains.annotations.ApiStatus.Experimental;%0A
 import org.j
@@ -843,16 +843,30 @@
 lable;%0A%0A
+@Experimental%0A
 public a
@@ -1515,16 +1515,23 @@
 ightType
+, fixes
 ) -%3E hol
@@ -1581,17 +1581,50 @@
 ightType
-)
+, fixes),%0A              isOnTheFly
 %0A       
@@ -1844,24 +1844,21 @@
   %7D%0A%0A  p
-rotected
+ublic
  interfa
@@ -1978,16 +1978,49 @@
  message
+, @NotNull LocalQuickFix... fixes
 ) %7B%0A    
@@ -2085,16 +2085,23 @@
 _WARNING
+, fixes
 );%0A    %7D
@@ -2259,16 +2259,260 @@
 ightType
+,%0A                   @NotNull LocalQuickFix... fixes);%0A  %7D%0A%0A  @Nullable%0A  protected JvmElementVisitor%3CBoolean%3E buildJvmVisitor(@NotNull Project project, @NotNull HighlightSink sink, boolean isOnTheFly) %7B%0A    return buildJvmVisitor(project, sink
 );%0A  %7D%0A%0A
@@ -2534,25 +2534,16 @@
 rotected
- abstract
  JvmElem
@@ -2631,16 +2631,35 @@
 ink 
-message);
+sink) %7B%0A    return null;%0A  %7D
 %0A%7D%0A

update JvmLocalInspection (IDEA-CR-31173)