private static void makeVariableFinalIfNeeded(
      InsertionContext context, @Nullable PsiReferenceExpression ref) {
    if (!Registry.is("java.completion.make.outer.variables.final")
        || ref == null
        || PsiUtil.isLanguageLevel8OrHigher(ref)
        || JspPsiUtil.isInJspFile(ref)) {
      return;
    }

    PsiElement target = ref.resolve();
    if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
      PsiClass placeClass =
          PsiTreeUtil.findElementOfClassAtOffset(
              context.getFile(), context.getTailOffset() - 1, PsiClass.class, false);
      if (placeClass != null
          && !PsiTreeUtil.isAncestor(placeClass, target, true)
          && !HighlightControlFlowUtil.isReassigned(
              (PsiVariable) target,
              new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) {
        PsiModifierList modifierList = ((PsiVariable) target).getModifierList();
        if (modifierList != null) {
          modifierList.setModifierProperty(PsiModifier.FINAL, true);
        }
      }
    }
  }
  public boolean convertLocalToField(final PsiLocalVariable local, final Editor editor) {
    boolean tempIsStatic = myIsConstant;
    PsiElement parent = local.getParent();
    List<PsiClass> classes = new ArrayList<>();

    if ("gr".equalsIgnoreCase(local.getContainingFile().getVirtualFile().getExtension())) {
      // this is special ij GW studio check for rule files
      CommonRefactoringUtil.showErrorHint(
          myProject,
          editor,
          "Introduce field is not supported for rule files",
          REFACTORING_NAME,
          HelpID.LOCAL_TO_FIELD);
      return false;
    }

    while (parent != null && parent.getContainingFile() != null) {
      if (parent instanceof PsiClass && !(myIsConstant && parent instanceof PsiAnonymousClass)) {
        classes.add((PsiClass) parent);
      }
      if (parent instanceof PsiFile && JspPsiUtil.isInJspFile(parent)) {
        String message = RefactoringBundle.message("error.not.supported.for.jsp", REFACTORING_NAME);
        CommonRefactoringUtil.showErrorHint(
            myProject, editor, message, REFACTORING_NAME, HelpID.LOCAL_TO_FIELD);
        return false;
      }
      if (parent instanceof PsiModifierListOwner
          && ((PsiModifierListOwner) parent).hasModifierProperty(PsiModifier.STATIC)) {
        tempIsStatic = true;
      }
      parent = parent.getParent();
    }

    if (classes.isEmpty()) {
      return false;
    }
    if (classes.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
      if (convertLocalToField(
          local, classes.get(getChosenClassIndex(classes)), editor, tempIsStatic)) {
        return false;
      }
    } else {
      final boolean isStatic = tempIsStatic;
      NavigationUtil.getPsiElementPopup(
              classes.toArray(new PsiClass[classes.size()]),
              new PsiClassListCellRenderer(),
              "Choose class to introduce " + (myIsConstant ? "constant" : "field"),
              new PsiElementProcessor<PsiClass>() {
                @Override
                public boolean execute(@NotNull PsiClass aClass) {
                  convertLocalToField(local, aClass, editor, isStatic);
                  return false;
                }
              })
          .showInBestPositionFor(editor);
    }

    return true;
  }
  @Override
  public UsageGroup groupUsage(@NotNull Usage usage) {
    if (!(usage instanceof PsiElementUsage)) {
      return null;
    }
    final PsiElement psiElement = ((PsiElementUsage) usage).getElement();
    final PsiFile containingFile = psiElement.getContainingFile();
    if (containingFile == null) return null;

    PsiFile topLevelFile =
        InjectedLanguageManager.getInstance(containingFile.getProject())
            .getTopLevelFile(containingFile);

    if (!(topLevelFile instanceof PsiJavaFile) || topLevelFile instanceof JspFile) {
      return null;
    }
    PsiElement containingClass =
        topLevelFile == containingFile
            ? psiElement
            : InjectedLanguageManager.getInstance(containingFile.getProject())
                .getInjectionHost(containingFile);
    do {
      containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class, true);
      if (containingClass == null || ((PsiClass) containingClass).getQualifiedName() != null) break;
    } while (true);

    if (containingClass == null) {
      // check whether the element is in the import list
      PsiImportList importList = PsiTreeUtil.getParentOfType(psiElement, PsiImportList.class, true);
      if (importList != null) {
        final String fileName = getFileNameWithoutExtension(topLevelFile);
        final PsiClass[] classes = ((PsiJavaFile) topLevelFile).getClasses();
        for (final PsiClass aClass : classes) {
          if (fileName.equals(aClass.getName())) {
            containingClass = aClass;
            break;
          }
        }
      }
    } else {
      // skip JspClass synthetic classes.
      if (containingClass.getParent() instanceof PsiFile
          && JspPsiUtil.isInJspFile(containingClass)) {
        containingClass = null;
      }
    }

    if (containingClass != null) {
      return new ClassUsageGroup((PsiClass) containingClass);
    }

    final VirtualFile virtualFile = topLevelFile.getVirtualFile();
    if (virtualFile != null) {
      return new FileGroupingRule.FileUsageGroup(topLevelFile.getProject(), virtualFile);
    }
    return null;
  }
 @Override
 public boolean isApplicable(PsiExpression expr) {
   PsiType type = expr.getType();
   if (PsiType.BOOLEAN != type) return false;
   if (!expr.isPhysical()) return false;
   PsiElement parent = expr.getParent();
   if (!(parent instanceof PsiExpressionStatement)) return false;
   final PsiElement element = parent.getParent();
   if (!(element instanceof PsiCodeBlock)
       && !(JspPsiUtil.isInJspFile(element) && element instanceof PsiFile)) return false;
   return true;
 }
  private static void addReferencesInRange(
      ArrayList<ASTNode> array, TreeElement parent, int startOffset, int endOffset) {
    if (parent.getElementType() == JavaElementType.JAVA_CODE_REFERENCE
        || parent.getElementType() == JavaElementType.REFERENCE_EXPRESSION) {
      array.add(parent);
      return;
    }

    if (parent.getPsi() instanceof PsiFile && JspPsiUtil.isInJspFile(parent.getPsi())) {
      final JspFile jspFile = JspPsiUtil.getJspFile(parent.getPsi());
      JspClass jspClass = (JspClass) jspFile.getJavaClass();
      addReferencesInRange(array, (TreeElement) jspClass.getNode(), startOffset, endOffset);
      return;
    }

    addReferencesInRangeForComposite(array, parent, startOffset, endOffset);
  }
 @Override
 public void visitTryStatement(@NotNull PsiTryStatement statement) {
   super.visitTryStatement(statement);
   if (JspPsiUtil.isInJspFile(statement.getContainingFile())) {
     return;
   }
   if (m_ignoreTestCases) {
     if (TestUtils.isPartOfJUnitTestMethod(statement)) {
       return;
     }
     final PsiClass containingClass = PsiTreeUtil.getParentOfType(statement, PsiClass.class);
     if (containingClass != null && TestFrameworks.getInstance().isTestClass(containingClass)) {
       return;
     }
   }
   final PsiCatchSection[] catchSections = statement.getCatchSections();
   for (final PsiCatchSection section : catchSections) {
     checkCatchSection(section);
   }
 }
  @Nullable
  public ProblemDescriptor[] checkFile(
      @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
    // does not work in tests since CodeInsightTestCase copies file into temporary location
    if (ApplicationManager.getApplication().isUnitTestMode()) return null;
    if (file instanceof PsiJavaFile) {
      if (JspPsiUtil.isInJspFile(file)) return null;
      PsiJavaFile javaFile = (PsiJavaFile) file;

      PsiDirectory directory = javaFile.getContainingDirectory();
      if (directory == null) return null;
      PsiPackage dirPackage = JavaDirectoryService.getInstance().getPackage(directory);
      if (dirPackage == null) return null;
      PsiPackageStatement packageStatement = javaFile.getPackageStatement();

      // highlight the first class in the file only
      PsiClass[] classes = javaFile.getClasses();
      if (classes.length == 0 && packageStatement == null) return null;

      String packageName = dirPackage.getQualifiedName();
      if (!Comparing.strEqual(packageName, "", true) && packageStatement == null) {
        String description = JavaErrorMessages.message("missing.package.statement", packageName);

        return new ProblemDescriptor[] {
          manager.createProblemDescriptor(
              classes[0].getNameIdentifier(),
              description,
              new AdjustPackageNameFix(javaFile, null, dirPackage),
              ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
              isOnTheFly)
        };
      }
      if (packageStatement != null) {
        final PsiJavaCodeReferenceElement packageReference = packageStatement.getPackageReference();
        PsiPackage classPackage = (PsiPackage) packageReference.resolve();
        List<LocalQuickFix> availableFixes = new ArrayList<LocalQuickFix>();
        if (classPackage == null) {
          availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage));
        } else if (!Comparing.equal(
            dirPackage.getQualifiedName(), packageReference.getText(), true)) {
          availableFixes.add(new AdjustPackageNameFix(javaFile, packageStatement, dirPackage));
          MoveToPackageFix moveToPackageFix = new MoveToPackageFix(file, classPackage);
          if (moveToPackageFix.isAvailable()) {
            availableFixes.add(moveToPackageFix);
          }
        }
        if (!availableFixes.isEmpty()) {
          String description =
              JavaErrorMessages.message(
                  "package.name.file.path.mismatch",
                  packageReference.getText(),
                  dirPackage.getQualifiedName());
          return new ProblemDescriptor[] {
            manager.createProblemDescriptor(
                packageStatement.getPackageReference(),
                description,
                isOnTheFly,
                availableFixes.toArray(new LocalQuickFix[availableFixes.size()]),
                ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
          };
        }
      }
    }
    return null;
  }