mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-12360 Several improvements in pep8 external annotator
* Various E3xx errors about blank lines are reported on corresponding PSI whitespaces, not at the following elements * Do not report missing blank line at the end of file if "Settings | Editor | Other | Ensure line feed on Save" is enabled * It that option was not enabled report W292 error on the last element in file * Suppress pep8 errors about redundant blanks if they conflict with preferences in Python's code style settings
This commit is contained in:
@@ -47,16 +47,22 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix;
|
||||
import com.jetbrains.python.formatter.PyCodeStyleSettings;
|
||||
import com.jetbrains.python.inspections.PyPep8Inspection;
|
||||
import com.jetbrains.python.inspections.quickfix.ReformatFix;
|
||||
import com.jetbrains.python.inspections.quickfix.RemoveTrailingBlankLinesFix;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.sdk.PreferredSdkComparator;
|
||||
import com.jetbrains.python.sdk.PySdkUtil;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
@@ -76,6 +82,7 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotator.State, Pep8ExternalAnnotator.Results> {
|
||||
private static final Logger LOG = Logger.getInstance(Pep8ExternalAnnotator.class);
|
||||
private static final Pattern E303_LINE_COUNT_PATTERN = Pattern.compile(".*\\((\\d+)\\)$");
|
||||
|
||||
public static class Problem {
|
||||
private final int myLine;
|
||||
@@ -222,32 +229,41 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
|
||||
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
|
||||
for (Problem problem : annotationResult.problems) {
|
||||
if (ignoreDueToSettings(project, problem)) continue;
|
||||
final int line = problem.myLine - 1;
|
||||
final int column = problem.myColumn - 1;
|
||||
int offset;
|
||||
if (document != null) {
|
||||
offset = line >= document.getLineCount() ? document.getTextLength()-1 : document.getLineStartOffset(line) + column;
|
||||
offset = line >= document.getLineCount() ? document.getTextLength() - 1 : document.getLineStartOffset(line) + column;
|
||||
}
|
||||
else {
|
||||
offset = StringUtil.lineColToOffset(text, line, column);
|
||||
}
|
||||
PsiElement problemElement = file.findElementAt(offset);
|
||||
if (!(problemElement instanceof PsiWhiteSpace) && !(problem.myCode.startsWith("E3"))) {
|
||||
final PsiElement elementAfter = file.findElementAt(offset + 1);
|
||||
if (elementAfter instanceof PsiWhiteSpace) {
|
||||
problemElement = elementAfter;
|
||||
// E3xx - blank lines warnings
|
||||
if (!(problemElement instanceof PsiWhiteSpace) && problem.myCode.startsWith("E3")) {
|
||||
final PsiElement elementBefore = file.findElementAt(Math.max(0, offset - 1));
|
||||
if (elementBefore instanceof PsiWhiteSpace) {
|
||||
problemElement = elementBefore;
|
||||
}
|
||||
}
|
||||
// W292 no newline at end of file
|
||||
if (problemElement == null && document != null && offset == document.getTextLength() && problem.myCode.equals("W292")) {
|
||||
problemElement = file.findElementAt(Math.max(0, offset - 1));
|
||||
}
|
||||
|
||||
if (ignoreDueToSettings(project, problem, problemElement)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (problemElement != null) {
|
||||
TextRange problemRange = problemElement.getTextRange();
|
||||
if (crossesLineBoundary(document, text, problemRange)) {
|
||||
int lineEndOffset;
|
||||
if (!(problemElement instanceof PsiWhiteSpace) && crossesLineBoundary(document, text, problemRange)) {
|
||||
final int lineEndOffset;
|
||||
if (document != null) {
|
||||
lineEndOffset = line >= document.getLineCount() ? document.getTextLength()-1 : document.getLineEndOffset(line);
|
||||
lineEndOffset = line >= document.getLineCount() ? document.getTextLength() - 1 : document.getLineEndOffset(line);
|
||||
}
|
||||
else {
|
||||
lineEndOffset = StringUtil.lineColToOffset(text, line+1, 0) - 1;
|
||||
lineEndOffset = StringUtil.lineColToOffset(text, line + 1, 0) - 1;
|
||||
}
|
||||
if (offset > lineEndOffset) {
|
||||
// PSI/document don't match, don't try to highlight random places
|
||||
@@ -296,15 +312,48 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator<Pep8ExternalAnnotat
|
||||
return StringUtil.offsetToLineNumber(text, start) != StringUtil.offsetToLineNumber(text, end);
|
||||
}
|
||||
|
||||
private static boolean ignoreDueToSettings(Project project, Problem problem) {
|
||||
String stripTrailingSpaces = EditorSettingsExternalizable.getInstance().getStripTrailingSpaces();
|
||||
if (!stripTrailingSpaces.equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE)) {
|
||||
private static boolean ignoreDueToSettings(Project project, Problem problem, PsiElement element) {
|
||||
final EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
|
||||
if (!editorSettings.getStripTrailingSpaces().equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE)) {
|
||||
// ignore trailing spaces errors if they're going to disappear after save
|
||||
if (problem.myCode.equals("W291") || problem.myCode.equals("W293")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
boolean useTabs = CodeStyleSettingsManager.getSettings(project).useTabCharacter(PythonFileType.INSTANCE);
|
||||
// W292 no newline at end of file
|
||||
if (editorSettings.isEnsureNewLineAtEOF() && problem.myCode.equals("W292")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
|
||||
final CommonCodeStyleSettings commonSettings = codeStyleSettings.getCommonSettings(PythonLanguage.getInstance());
|
||||
final PyCodeStyleSettings pySettings = codeStyleSettings.getCustomSettings(PyCodeStyleSettings.class);
|
||||
// E303 too many blank lines (num)
|
||||
if (problem.myCode.equals("E303") && element instanceof PsiWhiteSpace) {
|
||||
final Matcher matcher = E303_LINE_COUNT_PATTERN.matcher(problem.myDescription);
|
||||
if (matcher.matches()) {
|
||||
final int reportedBlanks = Integer.parseInt(matcher.group(1));
|
||||
final PsiElement nonWhitespaceAfter = PyPsiUtils.getNextNonWhitespaceSibling(element);
|
||||
final PsiElement nonWhitespaceBefore = PyPsiUtils.getPrevNonWhitespaceSibling(element);
|
||||
final boolean classNearby = nonWhitespaceBefore instanceof PyClass || nonWhitespaceAfter instanceof PyClass;
|
||||
final boolean functionNearby = nonWhitespaceBefore instanceof PyFunction || nonWhitespaceAfter instanceof PyFunction;
|
||||
if (functionNearby || classNearby) {
|
||||
if (PyUtil.isTopLevel(element)) {
|
||||
if (reportedBlanks <= pySettings.BLANK_LINES_AROUND_TOP_LEVEL_CLASSES_FUNCTIONS) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Blanks around classes have priority over blanks around functions as defined in Python spacing builder
|
||||
if (classNearby && reportedBlanks <= commonSettings.BLANK_LINES_AROUND_CLASS ||
|
||||
functionNearby && reportedBlanks <= commonSettings.BLANK_LINES_AROUND_METHOD) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final boolean useTabs = codeStyleSettings.useTabCharacter(PythonFileType.INSTANCE);
|
||||
if (useTabs && problem.myCode.equals("W191")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user