diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e8089..3836989 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ ## [Unreleased] +## [0.5.9] +### Changed +- Added a max lines feature to exclude big files +- Added a max problems per line feature + ## [0.5.8] ### Fixed - Fixed settings not opening with non default locales diff --git a/gradle.properties b/gradle.properties index 3a4ebf5..55c18a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ pluginGroup = org.OverEngineer pluginName = InlineProblems pluginRepositoryUrl = https://github.com/OverEngineer/InlineProblems # SemVer format -> https://semver.org -pluginVersion = 0.5.8 +pluginVersion = 0.5.9 # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html pluginSinceBuild = 212.5 diff --git a/src/main/java/org/overengineer/inlineproblems/DocumentMarkupModelScanner.java b/src/main/java/org/overengineer/inlineproblems/DocumentMarkupModelScanner.java index 36a3173..36bf494 100644 --- a/src/main/java/org/overengineer/inlineproblems/DocumentMarkupModelScanner.java +++ b/src/main/java/org/overengineer/inlineproblems/DocumentMarkupModelScanner.java @@ -19,7 +19,7 @@ import org.overengineer.inlineproblems.entities.enums.Listener; import org.overengineer.inlineproblems.listeners.HighlightProblemListener; import org.overengineer.inlineproblems.settings.SettingsState; -import org.overengineer.inlineproblems.utils.FileNameUtil; +import org.overengineer.inlineproblems.utils.FileUtil; import java.util.ArrayList; import java.util.Arrays; @@ -92,16 +92,20 @@ public void scanForProblemsManually() { FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); for (var editor : fileEditorManager.getAllEditors()) { - if (editor.getFile() == null || FileNameUtil.ignoreFile(editor.getFile().getName())) { + if (editor instanceof TextEditor) { + var textEditor = (TextEditor) editor; + + if ( + editor.getFile() == null || + FileUtil.ignoreFile(editor.getFile().getName(), textEditor.getEditor().getDocument().getLineCount()) + ) { continue; } - if (editor instanceof TextEditor) { - var textEditor = (TextEditor) editor; - problems.addAll(getProblemsInEditor(textEditor)); - } + problems.addAll(getProblemsInEditor(textEditor)); } } + } problemManager.updateFromNewActiveProblems(problems); } @@ -112,7 +116,10 @@ public void scanForProblemsManually() { * millisecond if the HighlightProblemListener is used. */ public void scanForProblemsManuallyInTextEditor(TextEditor textEditor) { - if (textEditor.getFile() == null || FileNameUtil.ignoreFile(textEditor.getFile().getName())) { + if ( + textEditor.getFile() == null || + FileUtil.ignoreFile(textEditor.getFile().getName(), textEditor.getEditor().getDocument().getLineCount()) + ) { return; } diff --git a/src/main/java/org/overengineer/inlineproblems/ListenerManager.java b/src/main/java/org/overengineer/inlineproblems/ListenerManager.java index 30b799d..0d8452b 100644 --- a/src/main/java/org/overengineer/inlineproblems/ListenerManager.java +++ b/src/main/java/org/overengineer/inlineproblems/ListenerManager.java @@ -9,7 +9,7 @@ import org.overengineer.inlineproblems.listeners.HighlightProblemListener; import org.overengineer.inlineproblems.listeners.MarkupModelProblemListener; import org.overengineer.inlineproblems.settings.SettingsState; -import org.overengineer.inlineproblems.utils.FileNameUtil; +import org.overengineer.inlineproblems.utils.FileUtil; public class ListenerManager { @@ -40,12 +40,15 @@ public void installMarkupModelListenerOnAllProjects() { for (var project : manager.getOpenProjects()) { FileEditorManager fileEditorManager = FileEditorManager.getInstance(project); for (var editor : fileEditorManager.getAllEditors()) { - - if (editor.getFile() == null || FileNameUtil.ignoreFile(editor.getFile().getName())) { - continue; - } - if (editor instanceof TextEditor) { + var textEditor = (TextEditor) editor; + if ( + editor.getFile() == null || + FileUtil.ignoreFile(editor.getFile().getName(), textEditor.getEditor().getDocument().getLineCount()) + ) { + continue; + } + MarkupModelProblemListener.setup((TextEditor) editor); logger.debug("Installing MarkupModelListener"); } diff --git a/src/main/java/org/overengineer/inlineproblems/ProblemManager.java b/src/main/java/org/overengineer/inlineproblems/ProblemManager.java index b35f2e4..c8b877a 100644 --- a/src/main/java/org/overengineer/inlineproblems/ProblemManager.java +++ b/src/main/java/org/overengineer/inlineproblems/ProblemManager.java @@ -64,6 +64,12 @@ public void addProblem(InlineProblem problem) { removeProblem(p); }); + // Limit problems per line + int maxProblemsPerLine = settingsState.getMaxProblemsPerLine(); + if (maxProblemsPerLine > 0 && problemsInLine.size() > maxProblemsPerLine) { + problemsInLine.subList(maxProblemsPerLine, problemsInLine.size()).clear(); + } + /* This only works when using a method reference, if we move the code from the addProblemPrivate func into a lambda * it does not work like expected, that is because there are differences in the evaluation and the way it is called */ problemsInLine.forEach(this::addProblemPrivate); diff --git a/src/main/java/org/overengineer/inlineproblems/listeners/FileEditorListener.java b/src/main/java/org/overengineer/inlineproblems/listeners/FileEditorListener.java index aab7a87..2faba81 100644 --- a/src/main/java/org/overengineer/inlineproblems/listeners/FileEditorListener.java +++ b/src/main/java/org/overengineer/inlineproblems/listeners/FileEditorListener.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.overengineer.inlineproblems.entities.enums.Listener; import org.overengineer.inlineproblems.settings.SettingsState; -import org.overengineer.inlineproblems.utils.FileNameUtil; +import org.overengineer.inlineproblems.utils.FileUtil; import java.util.Arrays; @@ -24,13 +24,15 @@ public void fileOpenedSync( if (settingsState.getEnabledListener() != Listener.MARKUP_MODEL_LISTENER) return; - if (FileNameUtil.ignoreFile(file.getName())) { + // Precheck only file name, later we check the line count only + if (FileUtil.ignoreFile(file.getName(), -1)) { return; } Arrays.stream(editors.first) - .filter(e -> e instanceof TextEditor) - .map(e -> (TextEditor)e) - .forEach(MarkupModelProblemListener::setup); + .filter(e -> e instanceof TextEditor) + .map(e -> (TextEditor) e) + .filter(tE -> !FileUtil.ignoreFile(null, tE.getEditor().getDocument().getLineCount())) + .forEach(MarkupModelProblemListener::setup); } } diff --git a/src/main/java/org/overengineer/inlineproblems/listeners/HighlightProblemListener.java b/src/main/java/org/overengineer/inlineproblems/listeners/HighlightProblemListener.java index 4939646..307c0e4 100644 --- a/src/main/java/org/overengineer/inlineproblems/listeners/HighlightProblemListener.java +++ b/src/main/java/org/overengineer/inlineproblems/listeners/HighlightProblemListener.java @@ -12,7 +12,7 @@ import org.overengineer.inlineproblems.DocumentMarkupModelScanner; import org.overengineer.inlineproblems.entities.enums.Listener; import org.overengineer.inlineproblems.settings.SettingsState; -import org.overengineer.inlineproblems.utils.FileNameUtil; +import org.overengineer.inlineproblems.utils.FileUtil; public class HighlightProblemListener implements HighlightInfoFilter { @@ -29,7 +29,8 @@ public boolean accept(@NotNull HighlightInfo highlightInfo, @Nullable PsiFile fi if (file == null || !file.isValid()) return true; - if (FileNameUtil.ignoreFile(file.getName())) { + // Only check file name here, the line count is checked in the scanForProblemsManuallyInTextEditor call + if (FileUtil.ignoreFile(file.getName(), -1)) { return true; } @@ -48,7 +49,7 @@ public void handleAccept(PsiFile file) { return; FileEditor editor = FileEditorManager.getInstance(file.getProject()).getSelectedEditor(file.getVirtualFile()); - if (editor == null) { + if (editor == null || !(editor instanceof TextEditor)) { return; } diff --git a/src/main/java/org/overengineer/inlineproblems/settings/SettingsComponent.java b/src/main/java/org/overengineer/inlineproblems/settings/SettingsComponent.java index 89f6079..dd02243 100644 --- a/src/main/java/org/overengineer/inlineproblems/settings/SettingsComponent.java +++ b/src/main/java/org/overengineer/inlineproblems/settings/SettingsComponent.java @@ -68,6 +68,8 @@ public class SettingsComponent { private final JBCheckBox enableXmlUnescaping = new JBCheckBox(SettingsBundle.message("settings.enableXmlUnescaping")); private final JFormattedTextField inlayFontSizeDeltaText; private final JFormattedTextField manualScannerDelay; + private final JFormattedTextField maxProblemsPerLine; + private final JFormattedTextField maxFileLines; private final JBCheckBox fillProblemLabels = new JBCheckBox(SettingsBundle.message("settings.fillProblemLabels")); private final JBCheckBox boldProblemLabels = new JBCheckBox(SettingsBundle.message("settings.boldProblemLabels")); private final JBCheckBox italicProblemLabels = new JBCheckBox(SettingsBundle.message("settings.italicProblemLabels")); @@ -135,9 +137,15 @@ public SettingsComponent() { inlayFontSizeDeltaText = new JFormattedTextField(numberFormatter); inlayFontSizeDeltaText.setText(Integer.toString(settingsState.getInlayFontSizeDelta())); + maxProblemsPerLine = new JFormattedTextField(numberFormatter); + maxProblemsPerLine.setText(Integer.toString(settingsState.getMaxProblemsPerLine())); + manualScannerDelay = new JFormattedTextField(numberFormatter); manualScannerDelay.setText(Integer.toString(settingsState.getManualScannerDelay())); + maxFileLines = new JFormattedTextField(numberFormatter); + maxFileLines.setText(Integer.toString(settingsState.getMaxFileLines())); + fillProblemLabels.setSelected(settingsState.isFillProblemLabels()); boldProblemLabels.setSelected(settingsState.isBoldProblemLabels()); italicProblemLabels.setSelected(settingsState.isItalicProblemLabels()); @@ -186,6 +194,10 @@ public SettingsComponent() { .addTooltip(SettingsBundle.message("settings.problemFilterListTooltip")) .addLabeledComponent(new JLabel(SettingsBundle.message("settings.fileExtensionBlacklistLabel")), fileExtensionBlacklist) .addTooltip(SettingsBundle.message("settings.fileExtensionBlacklistTooltip")) + .addLabeledComponent(new JBLabel(SettingsBundle.message("settings.maxProblemsPerLineLabel")), maxProblemsPerLine) + .addTooltip(SettingsBundle.message("settings.maxProblemsPerLineTooltip")) + .addLabeledComponent(new JLabel(SettingsBundle.message("settings.maxFileLinesLabel")), maxFileLines) + .addTooltip(SettingsBundle.message("settings.maxFileLinesTooltip")) .addSeparator() .addComponent(new JBLabel(SettingsBundle.message("settings.submenu.colors"))) .addComponent(showErrors) @@ -644,4 +656,30 @@ public int getManualScannerDelay() { public void setManualScannerDelay(int delay) { manualScannerDelay.setText(Integer.toString(Math.max(10, delay))); } + + public int getMaxProblemsPerLine() { + try { + return Math.max(Integer.parseInt(maxProblemsPerLine.getText()), 0); + } + catch (NumberFormatException e) { + return 0; + } + } + + public void setMaxProblemsPerLine(int max) { + maxProblemsPerLine.setText(Integer.toString(Math.max(0, max))); + } + + public int getMaxFileLines() { + try { + return Math.max(Integer.parseInt(maxFileLines.getText()), 0); + } + catch (NumberFormatException e) { + return 0; + } + } + + public void setMaxFileLines(int lines) { + maxFileLines.setText(Integer.toString(Math.max(0, lines))); + } } diff --git a/src/main/java/org/overengineer/inlineproblems/settings/SettingsConfigurable.java b/src/main/java/org/overengineer/inlineproblems/settings/SettingsConfigurable.java index f26c328..49bf284 100644 --- a/src/main/java/org/overengineer/inlineproblems/settings/SettingsConfigurable.java +++ b/src/main/java/org/overengineer/inlineproblems/settings/SettingsConfigurable.java @@ -48,6 +48,7 @@ public boolean isModified() { state.isRoundedCornerBoxes() == settingsComponent.isRoundedCornerBoxes() && state.isUseEditorFont() == settingsComponent.isUseEditorFont() && state.isShowOnlyHighestSeverityPerLine() == settingsComponent.isShowOnlyHighestSeverityPerLine() && + state.getMaxProblemsPerLine() == settingsComponent.getMaxProblemsPerLine() && state.isEnableHtmlStripping() == settingsComponent.isEnableHtmlStripping() && state.isEnableXmlUnescaping() == settingsComponent.isEnableXmlUnescaping() && state.getInlayFontSizeDelta() == settingsComponent.getInlayFontSizeDelta() && @@ -89,6 +90,7 @@ public boolean isModified() { state.getProblemFilterList().equals(settingsComponent.getProblemFilterList()) && state.getFileExtensionBlacklist().equals(settingsComponent.getFileExtensionBlacklist()) && + state.getMaxFileLines() == settingsComponent.getMaxFileLines() && state.getAdditionalInfoSeveritiesAsString().equals(settingsComponent.getAdditionalInfoSeverities()) && state.getAdditionalWarningSeveritiesAsString().equals(settingsComponent.getAdditionalWarningSeverities()) && @@ -106,6 +108,7 @@ public void apply() { boolean listenerChanged = state.getEnabledListener() != settingsComponent.getEnabledListener(); boolean fileExtensionBlacklistChanged = !Objects.equals(state.getFileExtensionBlacklist(), settingsComponent.getFileExtensionBlacklist()); boolean manualScannerDelayChanged = state.getManualScannerDelay() != settingsComponent.getManualScannerDelay(); + boolean maxFileLinesChanged = state.getMaxFileLines() != settingsComponent.getMaxFileLines(); state.setShowErrors(settingsComponent.isShowErrors()); state.setHighlightErrors(settingsComponent.isHighlightErrors()); @@ -143,6 +146,7 @@ public void apply() { state.setRoundedCornerBoxes(settingsComponent.isRoundedCornerBoxes()); state.setUseEditorFont(settingsComponent.isUseEditorFont()); state.setShowOnlyHighestSeverityPerLine(settingsComponent.isShowOnlyHighestSeverityPerLine()); + state.setMaxProblemsPerLine(settingsComponent.getMaxProblemsPerLine()); state.setEnableHtmlStripping(settingsComponent.isEnableHtmlStripping()); state.setEnableXmlUnescaping(settingsComponent.isEnableXmlUnescaping()); state.setInlayFontSizeDelta(settingsComponent.getInlayFontSizeDelta()); @@ -155,6 +159,7 @@ public void apply() { state.setManualScannerDelay(settingsComponent.getManualScannerDelay()); state.setProblemFilterList(settingsComponent.getProblemFilterList()); state.setFileExtensionBlacklist(settingsComponent.getFileExtensionBlacklist()); + state.setMaxFileLines(settingsComponent.getMaxFileLines()); state.setAdditionalInfoSeverities(settingsComponent.getAdditionalInfoSeveritiesList()); state.setAdditionalWarningSeverities(settingsComponent.getAdditionalWarningSeveritiesList()); @@ -167,8 +172,8 @@ public void apply() { listenerManager.resetAndRescan(); - // When the blacklist changes we need to re-apply all MarkupModelProblemListeners - if (fileExtensionBlacklistChanged && state.getEnabledListener() == Listener.MARKUP_MODEL_LISTENER) { + // When the blacklist or maxFileLines changes we need to re-apply all MarkupModelProblemListeners + if ((fileExtensionBlacklistChanged || maxFileLinesChanged) && state.getEnabledListener() == Listener.MARKUP_MODEL_LISTENER) { listenerManager.resetMarkupModelProblemListeners(); } @@ -217,6 +222,7 @@ public void reset() { settingsComponent.setRoundedCornerBoxes(state.isRoundedCornerBoxes()); settingsComponent.setUseEditorFont(state.isUseEditorFont()); settingsComponent.setShowOnlyHighestSeverityPerLine(state.isShowOnlyHighestSeverityPerLine()); + settingsComponent.setMaxProblemsPerLine(state.getMaxProblemsPerLine()); settingsComponent.setEnableHtmlStripping(state.isEnableHtmlStripping()); settingsComponent.setEnableXmlUnescaping(state.isEnableXmlUnescaping()); settingsComponent.setInlayFontSizeDelta(state.getInlayFontSizeDelta()); diff --git a/src/main/java/org/overengineer/inlineproblems/settings/SettingsState.java b/src/main/java/org/overengineer/inlineproblems/settings/SettingsState.java index e821f88..e585fea 100644 --- a/src/main/java/org/overengineer/inlineproblems/settings/SettingsState.java +++ b/src/main/java/org/overengineer/inlineproblems/settings/SettingsState.java @@ -100,6 +100,7 @@ public class SettingsState implements PersistentStateComponent { private int enabledListener = Listener.MARKUP_MODEL_LISTENER; private String problemFilterList = "todo;fixme;open in browser"; private String fileExtensionBlacklist = ""; + private int maxFileLines = 0; private List additionalErrorSeverities = new ArrayList<>(); private List additionalWarningSeverities = new ArrayList<>(); @@ -109,6 +110,7 @@ public class SettingsState implements PersistentStateComponent { private boolean showOnlyHighestSeverityPerLine = false; private boolean enableHtmlStripping = true; private boolean enableXmlUnescaping = true; + private int maxProblemsPerLine = 20; // migration booleans private boolean highlightProblemListenerDeprecateMigrationDone = false; diff --git a/src/main/java/org/overengineer/inlineproblems/utils/FileNameUtil.java b/src/main/java/org/overengineer/inlineproblems/utils/FileNameUtil.java deleted file mode 100644 index 94bd09e..0000000 --- a/src/main/java/org/overengineer/inlineproblems/utils/FileNameUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.overengineer.inlineproblems.utils; - -import org.overengineer.inlineproblems.settings.SettingsState; - -public class FileNameUtil { - public static boolean ignoreFile(String fileName) { - boolean ignore = false; - - for (var e : SettingsState.getInstance().getFileExtensionBlacklist().split(";")) { - if (e.isBlank() || e.isEmpty() || e.equals(";")) continue; - if (fileName.endsWith(e)) { - ignore = true; - break; - } - } - - return ignore; - } -} diff --git a/src/main/java/org/overengineer/inlineproblems/utils/FileUtil.java b/src/main/java/org/overengineer/inlineproblems/utils/FileUtil.java new file mode 100644 index 0000000..d112476 --- /dev/null +++ b/src/main/java/org/overengineer/inlineproblems/utils/FileUtil.java @@ -0,0 +1,37 @@ +package org.overengineer.inlineproblems.utils; + +import org.overengineer.inlineproblems.settings.SettingsState; + +public class FileUtil { + + /** + * Returns true if the file should be ignored, current checks involve the file name and the line count + * @param fileName can be null to ignore + * @param lineCount can be -1 to ignore + * @return true if the file should be ignored, false otherwise + */ + public static boolean ignoreFile(String fileName, int lineCount) { + boolean ignore = false; + var settings = SettingsState.getInstance(); + + if (fileName != null) { + for (var e : settings.getFileExtensionBlacklist().split(";")) { + if (e.isBlank() || e.isEmpty() || e.equals(";")) continue; + if (fileName.endsWith(e)) { + ignore = true; + break; + } + } + } + + if (lineCount >= 0) { + var maxFileLines = settings.getMaxFileLines(); + + if (maxFileLines >= 0 && lineCount >= maxFileLines) { + ignore = true; + } + } + + return ignore; + } +} diff --git a/src/main/resources/messages/SettingsBundle.properties b/src/main/resources/messages/SettingsBundle.properties index 08e3c7a..83b66b0 100644 --- a/src/main/resources/messages/SettingsBundle.properties +++ b/src/main/resources/messages/SettingsBundle.properties @@ -30,6 +30,8 @@ settings.problemFilterListLabel=Problem filter list settings.problemFilterListTooltip=Semicolon separated list of problem text beginnings that will not be handled settings.fileExtensionBlacklistLabel=File extension blacklist settings.fileExtensionBlacklistTooltip=Semicolon separated list of file extensions to ignore (like ".java;.md") +settings.maxFileLinesLabel=Maximum file lines +settings.maxFileLinesTooltip=Skip files with more lines than this value (0 = unlimited) settings.submenu.colors=Colors settings.errorTextColor=Error text color: settings.errorLabelBorderColor=Error label border color: @@ -51,6 +53,8 @@ settings.additionalSeveritiesInfoDesc=Semicolon separated list of additional inf settings.forceProblemsInOneLine=Force problems in the same line even if they are too long to fit settings.useEditorFont=Use editor font instead of tooltip font settings.showOnlyHighestPerLine=Show only the problem with the highest severity per line +settings.maxProblemsPerLineLabel=Max problems per line (0 = unlimited) +settings.maxProblemsPerLineTooltip=Limits the number of problems shown per line. Set to 0 for unlimited. settings.enableHtmlStripping=Enable stripping of HTML in the messages settings.enableXmlUnescaping=Enable unescaping of XML in the messages settings.enableClickableContext=Enable clickable inline problems for IDE context actions diff --git a/src/main/resources/messages/SettingsBundle_zh_CN.properties b/src/main/resources/messages/SettingsBundle_zh_CN.properties index 1a9a5ce..c700569 100644 --- a/src/main/resources/messages/SettingsBundle_zh_CN.properties +++ b/src/main/resources/messages/SettingsBundle_zh_CN.properties @@ -30,6 +30,8 @@ settings.problemFilterListLabel=\u95ee\u9898\u8fc7\u6ee4\u5217\u8868 settings.problemFilterListTooltip=\u4e0d\u5904\u7406\u7684\u95ee\u9898\u6587\u672c\u5f00\u5934\u7684\u7528\u5206\u53f7\u5206\u9694\u7684\u5217\u8868 settings.fileExtensionBlacklistLabel=File extension blacklist settings.fileExtensionBlacklistTooltip=Semicolon separated list of file extensions to ignore (like ".java;.md") +settings.maxFileLinesLabel=Maximum file lines +settings.maxFileLinesTooltip=Skip files with more lines than this value (0 = unlimited) settings.submenu.colors=\u989C\u8272 settings.errorTextColor=\u9519\u8BEF\u6587\u672C\u989C\u8272\uFF1A settings.errorLabelBorderColor=\u9519\u8BEF\u6807\u7B7E\u8FB9\u6846\u989C\u8272\uFF1A @@ -51,6 +53,8 @@ settings.additionalSeveritiesInfoDesc=\u9644\u52A0\u4FE1\u606F\u4E25\u91CD\u6027 settings.forceProblemsInOneLine=\u5F3A\u5236\u5728\u540C\u4E00\u884C\u663E\u793A\u95EE\u9898\uFF0C\u5373\u4F7F\u5B83\u4EEC\u592A\u957F\u800C\u65E0\u6CD5\u9002\u5E94 settings.useEditorFont=\u4F7F\u7528\u7F16\u8F91\u5668\u5B57\u4F53\u800C\u4E0D\u662F\u63D0\u793A\u5B57\u4F53 settings.showOnlyHighestPerLine=\u4ec5\u663e\u793a\u6bcf\u884c\u4e2d\u6700\u4e25\u91cd\u7684\u95ee\u9898 +settings.maxProblemsPerLineLabel=Max problems per line (0 = unlimited) +settings.maxProblemsPerLineTooltip=Limits the number of problems shown per line. Set to 0 for unlimited. settings.enableHtmlStripping=Enable stripping of HTML in the messages settings.enableXmlUnescaping=Enable unescaping of XML in the messages settings.enableClickableContext=Enable clickable inline problems for IDE context actions