PY-20033 New EP that allows to suppress individual PEP 8 errors in files

I've used it to create extension that mutes W292
(no new line at end of file) in IPython notebook cells.
This commit is contained in:
Mikhail Golubev
2016-08-11 15:05:03 +03:00
parent 3ed9034596
commit 6048a33767
5 changed files with 98 additions and 2 deletions
@@ -18,6 +18,7 @@
<extensions defaultExtensionNs="Pythonid">
<dialectsTokenSetContributor implementation="org.jetbrains.plugins.ipnb.psi.IpnbPyTokenSetContributor"/>
<visitorFilter language="IpnbPython" implementationClass="org.jetbrains.plugins.ipnb.IpnbVisitorFilter"/>
<pep8ProblemSuppressor implementation="org.jetbrains.plugins.ipnb.IpnbPep8ProblemSuppressor"/>
</extensions>
<actions>
<action class="org.jetbrains.plugins.ipnb.editor.actions.IpnbRunCellInplaceAction" id="IpnbRunCellInplaceAction"
@@ -0,0 +1,22 @@
package org.jetbrains.plugins.ipnb;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.validation.Pep8ExternalAnnotator;
import com.jetbrains.python.validation.Pep8ProblemSuppressor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.ipnb.psi.IpnbPyFragment;
/**
* @author Mikhail Golubev
*/
public class IpnbPep8ProblemSuppressor implements Pep8ProblemSuppressor {
@Override
public boolean isProblemSuppressed(@NotNull Pep8ExternalAnnotator.Problem problem,
@NotNull PsiFile file,
@Nullable PsiElement targetElement) {
// Ignore warnings about missing new line at the end of file inside IPython notebook cells
return file instanceof IpnbPyFragment && problem.getCode().equals("W292");
}
}
@@ -626,6 +626,7 @@
<extensionPoint qualifiedName="Pythonid.pyRootTypeProvider" interface="com.jetbrains.python.module.PyRootTypeProvider"/>
<extensionPoint qualifiedName="Pythonid.runConfigurationEditorExtension" interface="com.jetbrains.python.run.PyRunConfigurationEditorExtension"/>
<extensionPoint qualifiedName="Pythonid.pyCustomSdkUiProvider" interface="com.jetbrains.python.sdk.PyCustomSdkUiProvider"/>
<extensionPoint qualifiedName="Pythonid.pep8ProblemSuppressor" interface="com.jetbrains.python.validation.Pep8ProblemSuppressor"/>
</extensionPoints>
<extensions defaultExtensionNs="Pythonid">
@@ -68,6 +68,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
@@ -88,12 +89,30 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
private final String myCode;
private final String myDescription;
public Problem(int line, int column, String code, String description) {
public Problem(int line, int column, @NotNull String code, @NotNull String description) {
myLine = line;
myColumn = column;
myCode = code;
myDescription = description;
}
public int getLine() {
return myLine;
}
public int getColumn() {
return myColumn;
}
@NotNull
public String getCode() {
return myCode;
}
@NotNull
public String getDescription() {
return myDescription;
}
}
public static class State {
@@ -247,7 +266,7 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
problemElement = file.findElementAt(Math.max(0, offset - 1));
}
if (ignoreDueToSettings(project, problem, problemElement)) {
if (ignoreDueToSettings(project, problem, problemElement) || ignoredDueToProblemSuppressors(project, problem, file, problemElement)) {
continue;
}
@@ -297,6 +316,14 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
}
}
private static boolean ignoredDueToProblemSuppressors(@NotNull Project project,
@NotNull Problem problem,
@NotNull PsiFile file,
@Nullable PsiElement element) {
final Pep8ProblemSuppressor[] suppressors = Pep8ProblemSuppressor.EP_NAME.getExtensions();
return Arrays.stream(suppressors).anyMatch(p -> p.isProblemSuppressed(problem, file, element));
}
private static boolean crossesLineBoundary(@Nullable Document document, String text, TextRange problemRange) {
int start = problemRange.getStartOffset();
int end = problemRange.getEndOffset();
@@ -0,0 +1,45 @@
/*
* Copyright 2000-2016 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.validation;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Custom filter that allows to selectively suppress warnings and errors produced by pycodestyle.py (former pep8.py).
* Note that by using {@link com.jetbrains.python.inspections.PythonVisitorFilter} you can disable PEP 8 inspection for concrete files
* altogether.
*
* @author Mikhail Golubev
* @see Pep8ExternalAnnotator
* @see com.jetbrains.python.inspections.PythonVisitorFilter
*/
public interface Pep8ProblemSuppressor {
ExtensionPointName<Pep8ProblemSuppressor> EP_NAME = ExtensionPointName.create("Pythonid.pep8ProblemSuppressor");
/**
* @param problem a single problem returned by the script and extracted from its output
* @param file PSI file where the inspection operates
* @param targetElement PSI element found in the place of a problem on which annotation is going be attached in the editor
* @return whether notification about this problem should be hidden in the editor
*/
boolean isProblemSuppressed(@NotNull Pep8ExternalAnnotator.Problem problem,
@NotNull PsiFile file,
@Nullable PsiElement targetElement);
}