/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jetbrains.python.inspections;

import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.ProblemDescriptorImpl;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.util.ObjectUtils;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author dcheryasov
 */
public abstract class PyInspectionVisitor extends PyElementVisitor {
  @Nullable private final ProblemsHolder myHolder;
  @NotNull private final LocalInspectionToolSession mySession;
  protected final TypeEvalContext myTypeEvalContext;

  public static final Key<TypeEvalContext> INSPECTION_TYPE_EVAL_CONTEXT = Key.create("PyInspectionTypeEvalContext");

  public PyInspectionVisitor(@Nullable ProblemsHolder holder,
                             @NotNull LocalInspectionToolSession session) {
    myHolder = holder;
    mySession = session;
    TypeEvalContext context;
    synchronized (INSPECTION_TYPE_EVAL_CONTEXT) {
      context = session.getUserData(INSPECTION_TYPE_EVAL_CONTEXT);
      if (context == null) {
        final PsiFile sessionFile = session.getFile();
        final PsiFile contextFile = FileContextUtil.getContextFile(sessionFile);
        final PsiFile file = ObjectUtils.chooseNotNull(contextFile, sessionFile);

        context = TypeEvalContext.codeAnalysis(file.getProject(), file);
        session.putUserData(INSPECTION_TYPE_EVAL_CONTEXT, context);
      }
    }
    myTypeEvalContext = context;
  }

  protected PyResolveContext getResolveContext() {
    return PyResolveContext.defaultContext().withTypeEvalContext(myTypeEvalContext);
  }

  @Nullable
  protected ProblemsHolder getHolder() {
    return myHolder;
  }

  @NotNull
  public LocalInspectionToolSession getSession() {
    return mySession;
  }

  protected final void registerProblem(final PsiElement element,
                                       final String message) {
    if (element == null || element.getTextLength() == 0) {
      return;
    }
    if (myHolder != null) {
      myHolder.registerProblem(element, message);
    }
  }

  protected final void registerProblem(@Nullable final PsiElement element,
                                       @NotNull final String message,
                                       final LocalQuickFix @NotNull ... quickFixes) {
    if (element == null || element.getTextLength() == 0) {
      return;
    }
    if (myHolder != null) {
      myHolder.registerProblem(element, message, quickFixes);
    }
  }

  protected final void registerProblem(final PsiElement element,
                                       final String message,
                                       final ProblemHighlightType type) {
    if (element == null || element.getTextLength() == 0) {
      return;
    }
    if (myHolder != null) {
      myHolder.registerProblem(myHolder.getManager().createProblemDescriptor(element, message, (LocalQuickFix)null, type, myHolder.isOnTheFly()));
    }
  }

  /**
   * The most full-blown version.
   *
   * @see ProblemDescriptor
   */
  protected final void registerProblem(
    @NotNull final PsiElement psiElement,
    @NotNull final String descriptionTemplate,
    final ProblemHighlightType highlightType,
    @Nullable final HintAction hintAction,
    final LocalQuickFix... fixes) {
    registerProblem(psiElement, descriptionTemplate, highlightType, hintAction, null, fixes);
  }

  /**
   * The most full-blown version.
   *
   * @see ProblemDescriptor
   */
  protected final void registerProblem(
    @NotNull final PsiElement psiElement,
    @NotNull final String descriptionTemplate,
    final ProblemHighlightType highlightType,
    @Nullable final HintAction hintAction,
    @Nullable final TextRange rangeInElement,
    final LocalQuickFix... fixes) {
    if (myHolder != null && !(psiElement instanceof PsiErrorElement)) {
      myHolder.registerProblem(new ProblemDescriptorImpl(psiElement, psiElement, descriptionTemplate, fixes, highlightType, false,
                                                         rangeInElement, hintAction, myHolder.isOnTheFly()));
    }
  }
}

@@ -736,16 +736,75 @@
 orImpl;%0A
+import com.intellij.codeInspection.util.InspectionMessage;%0A
 import c
@@ -2833,37 +2833,41 @@
 registerProblem(
-final
+@Nullable
  PsiElement elem
@@ -2902,37 +2902,59 @@
                 
-final
+@NotNull @InspectionMessage
  String message)
@@ -3173,22 +3173,16 @@
 ullable 
-final 
 PsiEleme
@@ -3233,37 +3233,50 @@
        @NotNull 
-final
+@InspectionMessage
  String message,
@@ -3311,30 +3311,24 @@
             
-final 
 LocalQuickFi
@@ -3575,21 +3575,25 @@
 Problem(
-final
+@Nullable
  PsiElem
@@ -3644,21 +3644,43 @@
         
-final
+@NotNull @InspectionMessage
  String 
@@ -3723,28 +3723,31 @@
             
-fina
+@NotNul
 l ProblemHig
@@ -4154,38 +4154,32 @@
 m(%0A    @NotNull 
-final 
 PsiElement psiEl
@@ -4190,37 +4190,50 @@
 t,%0A    @NotNull 
-final
+@InspectionMessage
  String descript
@@ -4241,36 +4241,39 @@
 onTemplate,%0A    
-fina
+@NotNul
 l ProblemHighlig
@@ -4300,38 +4300,32 @@
 ,%0A    @Nullable 
-final 
 HintAction hintA
@@ -4331,30 +4331,24 @@
 Action,%0A    
-final 
 LocalQuickFi
@@ -4340,32 +4340,41 @@
    LocalQuickFix
+ @NotNull
 ... fixes) %7B%0A   
@@ -4601,22 +4601,16 @@
 NotNull 
-final 
 PsiEleme
@@ -4637,21 +4637,34 @@
 NotNull 
-final
+@InspectionMessage
  String 
@@ -4688,20 +4688,23 @@
 te,%0A    
-fina
+@NotNul
 l Proble
@@ -4747,22 +4747,16 @@
 ullable 
-final 
 HintActi
@@ -4784,22 +4784,16 @@
 ullable 
-final 
 TextRang
@@ -4814,22 +4814,16 @@
 nt,%0A    
-final 
 LocalQui
@@ -4827,16 +4827,25 @@
 QuickFix
+ @NotNull
 ... fixe

Add missing nullability and @Nls annotations in PyInspectionVisitor