package com.eslint.inspection;
import com.eslint.ESLintBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.actions.SuppressByCommentFix;
import com.intellij.codeInspection.CustomSuppressableInspectionTool;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.SuppressIntentionAction;
import com.intellij.codeInspection.SuppressQuickFix;
import com.intellij.lang.javascript.inspections.JSInspectionSuppressor;
import com.intellij.lang.javascript.linter.jshint.JSHintInspection;
import com.intellij.lang.javascript.psi.JSElement;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.lang.javascript.psi.impl.JSFileImpl;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PropertySuppressableInspectionBase extends LocalInspectionTool { //implements CustomSuppressableInspectionTool {
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.properties.PropertySuppressableInspectionBase");
@NotNull
public String getGroupDisplayName() {
return ESLintBundle.message("eslint.inspection.group.name");
}
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
PsiNamedElement pe = getProblemElement(element);
return new SuppressIntentionAction[]{new SuppressForStatement(getShortName()), new SuppressForFile(getShortName())};
}
@NotNull
public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) {
return new SuppressQuickFix[]{new ESLintSuppressByCommentFix(HighlightDisplayKey.find(this.getShortName()), JSInspectionSuppressor.getHolderClass(element))};
}
public static class ESLintSuppressByCommentFix extends SuppressByCommentFix {
public ESLintSuppressByCommentFix(HighlightDisplayKey key, Class<? extends PsiElement> suppressionHolderClass) {
super(key, suppressionHolderClass);
}
@NotNull
public String getText() {
return "Suppress for line";
}
protected void createSuppression(@NotNull Project project, @NotNull PsiElement element, @NotNull PsiElement container) throws IncorrectOperationException {
if (element.isValid()) {
PsiFile psiFile = element.getContainingFile();
if (psiFile != null) {
psiFile = psiFile.getOriginalFile();
}
if (psiFile != null && psiFile.isValid()) {
final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
if (document != null) {
int lineNo = document.getLineNumber(element.getTextOffset());
final int lineEndOffset = document.getLineEndOffset(lineNo);
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
public void run() {
document.insertString(lineEndOffset, " //eslint-disable-line");
}
}, null, null);
}
}
}
}
}
public boolean isSuppressedFor(@NotNull PsiElement element) {
// Property property = PsiTreeUtil.getParentOfType(element, Property.class, false);
// JSFileImpl file;
// if (property == null) {
// PsiFile containingFile = element.getContainingFile();
// if (containingFile instanceof JSFileImpl) {
// file = (JSFileImpl) containingFile;
// } else {
// return false;
// }
// } else {
// PsiElement prev = property.getPrevSibling();
// while (prev instanceof PsiWhiteSpace || prev instanceof PsiComment) {
// if (prev instanceof PsiComment) {
// @NonNls String text = prev.getText();
// if (text.contains("suppress") && text.contains('"' + getShortName() + '"')) return true;
// }
// prev = prev.getPrevSibling();
// }
// file = property.getPropertiesFile();
// }
// PsiElement leaf = file.getContainingFile().findElementAt(0);
// while (leaf instanceof PsiWhiteSpace) leaf = leaf.getNextSibling();
//
// while (leaf instanceof PsiComment) {
// @NonNls String text = leaf.getText();
// if (text.contains("suppress") && text.contains('"' + getShortName() + '"') && text.contains("file")) {
// return true;
// }
// leaf = leaf.getNextSibling();
// if (leaf instanceof PsiWhiteSpace) leaf = leaf.getNextSibling();
// // comment before first property get bound to the file, not property
// if (leaf instanceof PropertiesList && leaf.getFirstChild() == property && text.contains("suppress") && text.contains("\"" + getShortName() + "\"")) {
// return true;
// }
// }
return false;
}
private static class SuppressForStatement extends SuppressIntentionAction {
private final String rule;
public SuppressForStatement(String rule) {
this.rule = rule;
}
@NotNull
public String getText() {
return ESLintBundle.message("unused.property.suppress.for.statement");
}
@NotNull
public String getFamilyName() {
return ESLintBundle.message("unused.property.suppress.for.statement");
}
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
final JSElement property = PsiTreeUtil.getParentOfType(element, JSElement.class);
return property != null && property.isValid();
}
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
final PsiFile file = element.getContainingFile();
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
// InspectionManager inspectionManager = InspectionManager.getInstance(project);
// ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(element, element, "", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
final JSElement property = PsiTreeUtil.getParentOfType(element, JSElement.class);
LOG.assertTrue(property != null);
final int start = property.getTextRange().getStartOffset();
@NonNls final Document doc = PsiDocumentManager.getInstance(project).getDocument(file);
LOG.assertTrue(doc != null);
final int line = doc.getLineNumber(start);
final int lineEnd = doc.getLineEndOffset(line);
doc.insertString(lineEnd, " //eslint-disable-line " + rule);
}
}
private static class SuppressForFile extends SuppressIntentionAction {
private final String rule;
public SuppressForFile(String rule) {
this.rule = rule;
}
@NotNull
public String getText() {
return ESLintBundle.message("unused.property.suppress.for.file");
}
@NotNull
public String getFamilyName() {
return ESLintBundle.message("unused.property.suppress.for.file");
}
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
return element.isValid() && element.getContainingFile() instanceof JSFile;
}
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
final PsiFile file = element.getContainingFile();
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
@NonNls final Document doc = PsiDocumentManager.getInstance(project).getDocument(file);
LOG.assertTrue(doc != null, file);
// doc.insertString(0, "// eslint suppress inspection \"" + rule + "\" for whole file\n");
doc.insertString(0, "/* eslint-disable */\n");
}
}
//doc.insertString(lineStart, "/*eslint " + rule + ":0*/\n");
}