<commit_before>package de.plushnikov.intellij.plugin.extension;

import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
import de.plushnikov.intellij.plugin.util.PsiFieldUtil;
import lombok.experimental.Final;
import lombok.experimental.FinalArgs;
import org.jetbrains.annotations.NotNull;

/**
 * @author <NAME>
 * @version 1.0.36
 * @since 1.0.36
 */
public class LombokFinalAnnotator implements Annotator {
  private static final String MESSAGE_1 = "Final contains functionality of FinalArgs.";
  private static final String MESSAGE_2 = "%s can make final this variable without 'final' modifier";
  private static final String MESSAGE_3 = "FieldDefaults(makeFinal = true) can make final this field without 'final' modifier.";
  private AnnotationHolder holder;
  private PsiKeyword keyword;

  private static class RemoveFinalIntentionAction extends BaseIntentionAction {
    private PsiKeyword keyword;

    public RemoveFinalIntentionAction(PsiKeyword keyword) {
      this.keyword = keyword;
    }

    @NotNull @Override public String getText() { return getFamilyName(); }

    @NotNull @Override public String getFamilyName() { return "Remove 'final' modifier"; }

    @Override
    public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
      return this.keyword != null;
    }

    @Override
    public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
      this.keyword.delete();
    }
  }

  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!(element instanceof PsiKeyword) || !PsiKeyword.FINAL.equals(element.getText())) return;
    this.keyword = (PsiKeyword) element;
    this.holder = holder;

    PsiMethod parentMethod = PsiTreeUtil.getParentOfType(keyword, PsiMethod.class);
    PsiField parentField = PsiTreeUtil.getParentOfType(keyword, PsiField.class);

    if (parentMethod != null && parentField == null) handleLocalVariable(parentMethod);
    if (parentMethod == null && parentField != null) handleGlobalVariable(parentField);
  }

  public void handleLocalVariable(@NotNull final PsiMethod psiMethod) {
    PsiAnnotation finalAnnotation = PsiAnnotationUtil.findAnnotation(psiMethod, Final.class);
    PsiAnnotation finalArgsAnnotation = PsiAnnotationUtil.findAnnotation(psiMethod, FinalArgs.class);

    if (finalAnnotation != null && finalArgsAnnotation != null) holder.createWarningAnnotation(finalArgsAnnotation, MESSAGE_1).registerFix(new RemoveFinalIntentionAction(keyword));

    PsiVariable variable = PsiTreeUtil.getParentOfType(keyword, PsiVariable.class);
    if (PsiFieldUtil.isFinalByAnnotation(variable)) {
      if (finalArgsAnnotation != null) holder.createWarningAnnotation(keyword, String.format(MESSAGE_2, finalArgsAnnotation.getQualifiedName())).registerFix(new RemoveFinalIntentionAction(keyword));
      if (finalAnnotation != null) holder.createWarningAnnotation(keyword, String.format(MESSAGE_2, finalAnnotation.getQualifiedName())).registerFix(new RemoveFinalIntentionAction(keyword));
    }
  }

  public void handleGlobalVariable(@NotNull final PsiField psiField) {
    if (PsiFieldUtil.isFinalByAnnotation(psiField)) holder.createWarningAnnotation(keyword, MESSAGE_3).registerFix(new RemoveFinalIntentionAction(keyword));
  }
}<commit_msg>FW-536. @Final skip in 'for' declaration (fixed null variable)<commit_after>package de.plushnikov.intellij.plugin.extension;

import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import de.plushnikov.intellij.plugin.util.PsiAnnotationUtil;
import de.plushnikov.intellij.plugin.util.PsiFieldUtil;
import lombok.experimental.Final;
import lombok.experimental.FinalArgs;
import org.jetbrains.annotations.NotNull;

/**
 * @author <NAME>
 * @version 1.0.36
 * @since 1.0.36
 */
public class LombokFinalAnnotator implements Annotator {
  private static final String MESSAGE_1 = "Final contains functionality of FinalArgs.";
  private static final String MESSAGE_2 = "%s can make final this variable without 'final' modifier";
  private static final String MESSAGE_3 = "FieldDefaults(makeFinal = true) can make final this field without 'final' modifier.";
  private AnnotationHolder holder;
  private PsiKeyword keyword;

  private static class RemoveFinalIntentionAction extends BaseIntentionAction {
    private PsiKeyword keyword;

    public RemoveFinalIntentionAction(PsiKeyword keyword) {
      this.keyword = keyword;
    }

    @NotNull @Override public String getText() { return getFamilyName(); }

    @NotNull @Override public String getFamilyName() { return "Remove 'final' modifier"; }

    @Override
    public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
      return this.keyword != null;
    }

    @Override
    public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
      this.keyword.delete();
    }
  }

  @Override
  public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
    if (!(element instanceof PsiKeyword) || !PsiKeyword.FINAL.equals(element.getText())) return;
    this.keyword = (PsiKeyword) element;
    this.holder = holder;

    PsiMethod parentMethod = PsiTreeUtil.getParentOfType(keyword, PsiMethod.class);
    PsiField parentField = PsiTreeUtil.getParentOfType(keyword, PsiField.class);

    if (parentMethod != null && parentField == null) handleLocalVariable(parentMethod);
    if (parentMethod == null && parentField != null) handleGlobalVariable(parentField);
  }

  public void handleLocalVariable(@NotNull final PsiMethod psiMethod) {
    PsiAnnotation finalAnnotation = PsiAnnotationUtil.findAnnotation(psiMethod, Final.class);
    PsiAnnotation finalArgsAnnotation = PsiAnnotationUtil.findAnnotation(psiMethod, FinalArgs.class);

    if (finalAnnotation != null && finalArgsAnnotation != null) holder.createWarningAnnotation(finalArgsAnnotation, MESSAGE_1).registerFix(new RemoveFinalIntentionAction(keyword));

    PsiVariable variable = PsiTreeUtil.getParentOfType(keyword, PsiVariable.class);
    if (variable != null && PsiFieldUtil.isFinalByAnnotation(variable)) {
      if (finalArgsAnnotation != null) holder.createWarningAnnotation(keyword, String.format(MESSAGE_2, finalArgsAnnotation.getQualifiedName())).registerFix(new RemoveFinalIntentionAction(keyword));
      if (finalAnnotation != null) holder.createWarningAnnotation(keyword, String.format(MESSAGE_2, finalAnnotation.getQualifiedName())).registerFix(new RemoveFinalIntentionAction(keyword));
    }
  }

  public void handleGlobalVariable(@NotNull final PsiField psiField) {
    if (PsiFieldUtil.isFinalByAnnotation(psiField)) holder.createWarningAnnotation(keyword, MESSAGE_3).registerFix(new RemoveFinalIntentionAction(keyword));
  }
}
{'fraction_non_alphanumeric': 0.09493272978750157, 'fraction_numerical': 0.004149377593360996, 'mean_word_length': 5.723584108199493, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3321262', 'n_tokens_mistral': 2258, 'n_tokens_neox': 2201, 'n_words': 500}