diff --git a/CHANGELOG.md b/CHANGELOG.md
index 514040150..bf89235cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@
- Added shortcut `shift + alt + enter` for execute ImpEx action [#839](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/839)
- Added shortcut `control + alt + V` for Validate ImpEx action [#844](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/844)
- Added shortcut `control + shift + alt + O` for Open ImpEx action [#845](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/845)
+- Omit slow operation on Column Highlighting under the caret [#847](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/847)
### Other
- Adjust optional dependency on `AntPlugin` during project refresh [#833](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/833)
diff --git a/resources/META-INF/lang/impex-dependencies.xml b/resources/META-INF/lang/impex-dependencies.xml
index 3d46a3eca..620f0fad9 100644
--- a/resources/META-INF/lang/impex-dependencies.xml
+++ b/resources/META-INF/lang/impex-dependencies.xml
@@ -83,10 +83,6 @@
-
-
-
-
-
-
diff --git a/src/com/intellij/idea/plugin/hybris/impex/actions/AbstractImpExTableColumnMoveAction.kt b/src/com/intellij/idea/plugin/hybris/impex/actions/AbstractImpExTableColumnMoveAction.kt
index 2c11849ad..d429a0115 100644
--- a/src/com/intellij/idea/plugin/hybris/impex/actions/AbstractImpExTableColumnMoveAction.kt
+++ b/src/com/intellij/idea/plugin/hybris/impex/actions/AbstractImpExTableColumnMoveAction.kt
@@ -17,8 +17,7 @@
*/
package com.intellij.idea.plugin.hybris.impex.actions
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexColumnHighlighterService
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexHeaderNameHighlighterService
+import com.intellij.idea.plugin.hybris.impex.assistance.event.ImpexHighlightingCaretListener
import com.intellij.idea.plugin.hybris.impex.psi.ImpexFullHeaderParameter
import com.intellij.idea.plugin.hybris.impex.psi.ImpexHeaderLine
import com.intellij.idea.plugin.hybris.impex.psi.ImpexValueGroup
@@ -39,6 +38,8 @@ abstract class AbstractImpExTableColumnMoveAction(private val direction: ImpExCo
}
private fun move(editor: Editor, headerParameter: ImpexFullHeaderParameter, elementAtCaret: PsiElement, direction: ImpExColumnPosition) {
+ ImpexHighlightingCaretListener.instance.clearHighlightedArea(editor)
+
val headerLine = headerParameter.headerLine ?: return
val column = headerParameter.columnNumber
@@ -53,9 +54,6 @@ abstract class AbstractImpExTableColumnMoveAction(private val direction: ImpExCo
newElementAtCaret
?.let {
- ImpexColumnHighlighterService.instance.releaseEditorData(editor)
- ImpexHeaderNameHighlighterService.instance.releaseEditorData(editor)
-
val caretOffsetInText = previousOffset - previousElementStartOffset
editor.caretModel.currentCaret.moveToOffset(it.startOffset + caretOffsetInText)
}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/AbstractImpexHighlighterService.java b/src/com/intellij/idea/plugin/hybris/impex/assistance/AbstractImpexHighlighterService.java
deleted file mode 100644
index 7d778787f..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/AbstractImpexHighlighterService.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * This file is part of "hybris integration" plugin for Intellij IDEA.
- * Copyright (C) 2014-2016 Alexander Bartash
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance;
-
-import com.intellij.codeInsight.highlighting.HighlightManager;
-import com.intellij.codeInsight.highlighting.HighlightManagerImpl;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.markup.RangeHighlighter;
-import com.intellij.openapi.util.TextRange;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-public abstract class AbstractImpexHighlighterService implements ImpexHighlighterService {
-
- /**
- * IIPS-174: It seems like sometimes when we highlight code inside "Code Preview Panel" in combination with OOTB
- * "unchanged lines" folding from IDEA it can end up in creating invalid highlighting ranges.
- * E.g. when you run an inspection for an impex file and in the results panel click on an inspection result
- * on the right it shows you a preview of a snippet from that file, and if you have multiple inspection warnings in
- * the same file when you click on them the preview panel jumps into different parts of the file, which leads to
- * creation of multiple highlight ranges while the editor stays the same, but OOTB folding messes everything up by
- * folding many lines as the result highlight ranges created for the first inspection have invalid start and end
- * offsets for the editor with folded lines when you click on some other inspection from the same file.
- */
- protected void removeInvalidRangeHighlighters(@NotNull final Editor editor) {
- final HighlightManager highlightManager = HighlightManager.getInstance(
- Objects.requireNonNull(editor.getProject())
- );
-
- final RangeHighlighter[] highlighters = ((HighlightManagerImpl) highlightManager).getHighlighters(editor);
-
- Arrays.stream(highlighters)
- .filter(this::isNotProperRangeHighlighter)
- .forEach(highlighter -> highlightManager.removeSegmentHighlighter(editor, highlighter));
- }
-
- /**
- * From {@link TextRange#isProperRange(int, int) TextRange#isProperRange(int, int))
- */
- protected boolean isNotProperRangeHighlighter(@NotNull RangeHighlighter rangeHighlighter) {
- return rangeHighlighter.getStartOffset() > rangeHighlighter.getEndOffset() || rangeHighlighter.getStartOffset() < 0;
- }
-}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexColumnHighlighterService.java b/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexColumnHighlighterService.java
deleted file mode 100644
index 7d40983b4..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexColumnHighlighterService.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2014-2016 Alexander Bartash
- * Copyright (C) 2019-2023 EPAM Systems and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance;
-
-import com.intellij.codeInsight.folding.impl.FoldingUtil;
-import com.intellij.codeInsight.highlighting.HighlightManager;
-import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
-import com.intellij.idea.plugin.hybris.impex.psi.ImpexValue;
-import com.intellij.idea.plugin.hybris.impex.psi.ImpexValueGroup;
-import com.intellij.idea.plugin.hybris.impex.utils.ImpexPsiUtils;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.colors.EditorColors;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.SmartPointerManager;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.Validate;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-
-public class DefaultImpexColumnHighlighterService
- extends AbstractImpexHighlighterService
- implements ImpexColumnHighlighterService {
-
- private final static Key> CACHE_KEY = Key.create("IMPEX_COLUMN_HIGHLIGHT_CACHE");
-
- @Override
- @Contract
- public void highlight(@NotNull final Editor editor) {
- ApplicationManager.getApplication().invokeLater(() -> highlightColumnOfValueUnderCaret(editor));
- }
-
- @Contract
- protected void highlightColumnOfValueUnderCaret(@NotNull final Editor editor) {
- final var headerParameter = ImpexPsiUtils.getFullHeaderParameterUnderCaret(editor);
- if (headerParameter == null) {
- clearHighlightedArea(editor);
- return;
- }
-
- final var values = headerParameter.getValueGroups().stream()
- .map(ImpexValueGroup::getValue)
- .filter(Objects::nonNull)
- .toList();
-
- if (values.isEmpty()) {
- clearHighlightedArea(editor);
- } else if (editor.getProject() != null) {
- final var pointerManager = SmartPointerManager.getInstance(editor.getProject());
- highlightArea(editor, values);
- }
- }
-
- @Contract
- protected void highlightArea(
- @NotNull final Editor editor,
- final List values
- ) {
- if (isAlreadyHighlighted(editor, values)) {
- return;
- }
-
- final var currentHighlightedElement = editor.getUserData(CACHE_KEY);
- editor.putUserData(CACHE_KEY, null);
- if (null != currentHighlightedElement) {
- modifyHighlightedArea(editor, currentHighlightedElement, true);
- }
-
- editor.putUserData(CACHE_KEY, values);
- modifyHighlightedArea(editor, values, false);
- }
-
- @Contract
- protected void clearHighlightedArea(@NotNull final Editor editor) {
- final var column = editor.getUserData(CACHE_KEY);
- if (column != null) {
- editor.putUserData(CACHE_KEY, null);
- modifyHighlightedArea(editor, column, true);
- }
- }
-
- @Contract
- protected boolean isAlreadyHighlighted(
- @NotNull final Editor editor,
- final List ranges
- ) {
- return Objects.equals(editor.getUserData(CACHE_KEY), ranges);
- }
-
- @Contract
- protected void modifyHighlightedArea(
- @NotNull final Editor editor,
- final List column,
- final boolean clear
- ) {
- Validate.notNull(column);
-
- if (null == editor.getProject()) {
- return;
- }
-
- if (editor.getProject().isDisposed()) {
- return;
- }
-
- this.removeInvalidRangeHighlighters(editor);
-
- // This list must be modifiable
- // https://hybris-integration.atlassian.net/browse/IIP-11
- final List ranges = column
- .stream()
- .map(PsiElement::getTextRange)
- .filter(textRange -> !FoldingUtil.isTextRangeFolded(editor, textRange))
- // Do not use Collectors.toList() here because:
- // There are no guarantees on the type, mutability, serializability,
- // or thread-safety of the List returned; if more control over the
- // returned List is required, use toCollection(Supplier).
- .collect(Collectors.toCollection(ArrayList::new));
-
- if (CollectionUtils.isNotEmpty(ranges)) {
- HighlightUsagesHandler.highlightRanges(
- HighlightManager.getInstance(editor.getProject()),
- editor,
- EditorColors.SEARCH_RESULT_ATTRIBUTES,
- clear,
- ranges
- );
- }
- }
-
- @Override
- @Contract
- public void releaseEditorData(@NotNull final Editor editor) {
- editor.putUserData(CACHE_KEY, null);
- }
-
-}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexHeaderNameHighlighterService.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexHeaderNameHighlighterService.kt
deleted file mode 100644
index 29f531367..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/DefaultImpexHeaderNameHighlighterService.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2019-2023 EPAM Systems and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance
-
-import com.intellij.codeInsight.folding.impl.FoldingUtil
-import com.intellij.codeInsight.highlighting.HighlightManager
-import com.intellij.codeInsight.highlighting.HighlightUsagesHandler
-import com.intellij.idea.plugin.hybris.impex.utils.ImpexPsiUtils
-import com.intellij.openapi.application.invokeLater
-import com.intellij.openapi.editor.Editor
-import com.intellij.openapi.editor.colors.EditorColors
-import com.intellij.openapi.util.TextRange
-import com.intellij.psi.PsiElement
-
-class DefaultImpexHeaderNameHighlighterService : AbstractImpexHighlighterService(), ImpexHeaderNameHighlighterService {
-
- private val highlightedBlocks = mutableMapOf()
-
- override fun highlight(editor: Editor) {
- invokeLater {
- ImpexPsiUtils.getHeaderOfValueGroupUnderCaret(editor)
- ?.let { highlightArea(editor, it) }
- ?: clearHighlightedArea(editor)
- }
- }
-
- private fun highlightArea(
- editor: Editor,
- impexFullHeaderParameter: PsiElement
- ) {
- if (isAlreadyHighlighted(editor, impexFullHeaderParameter)) return
-
- highlightedBlocks.remove(editor)
- ?.let { modifyHighlightedArea(editor, it, true) }
-
- highlightedBlocks[editor] = impexFullHeaderParameter
- modifyHighlightedArea(editor, impexFullHeaderParameter)
- }
-
- private fun clearHighlightedArea(editor: Editor) {
- if (highlightedBlocks.isEmpty()) return
-
- val impexFullHeaderParameter = highlightedBlocks.remove(editor) ?: return
-
- modifyHighlightedArea(editor, impexFullHeaderParameter, true)
- }
-
- private fun isAlreadyHighlighted(editor: Editor, fullHeaderParameter: PsiElement) =
- highlightedBlocks[editor] == fullHeaderParameter
-
- private fun modifyHighlightedArea(
- editor: Editor,
- impexFullHeaderParameter: PsiElement,
- clear: Boolean = false,
- ) {
- val project = editor.project ?: return
- if (project.isDisposed) return
-
- removeInvalidRangeHighlighters(editor)
-
- if (FoldingUtil.isTextRangeFolded(editor, impexFullHeaderParameter.textRange)) return
-
- val ranges = mutableListOf()
- ranges.add(impexFullHeaderParameter.textRange)
-
- HighlightUsagesHandler.highlightRanges(
- HighlightManager.getInstance(project),
- editor,
- EditorColors.SEARCH_RESULT_ATTRIBUTES,
- clear,
- ranges
- )
- }
-
- override fun releaseEditorData(editor: Editor) {
- highlightedBlocks.remove(editor)
- }
-}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexColumnHighlighterService.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexColumnHighlighterService.kt
deleted file mode 100644
index 5bf33b19d..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexColumnHighlighterService.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of "hybris integration" plugin for Intellij IDEA.
- * Copyright (C) 2019 EPAM Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance;
-
-import com.intellij.openapi.application.ApplicationManager;
-
-interface ImpexColumnHighlighterService : ImpexHighlighterService {
-
- companion object {
- val instance: ImpexColumnHighlighterService = ApplicationManager.getApplication().getService(ImpexColumnHighlighterService::class.java)
- }
-}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHeaderNameHighlighterService.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHeaderNameHighlighterService.kt
deleted file mode 100644
index 7a5659159..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHeaderNameHighlighterService.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of "hybris integration" plugin for Intellij IDEA.
- * Copyright (C) 2019 EPAM Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance;
-
-import com.intellij.openapi.application.ApplicationManager;
-
-interface ImpexHeaderNameHighlighterService : ImpexHighlighterService {
-
- companion object {
- val instance: ImpexHeaderNameHighlighterService = ApplicationManager.getApplication().getService(ImpexHeaderNameHighlighterService::class.java)
- }
-}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHighlighterService.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHighlighterService.kt
deleted file mode 100644
index b9d1d74c7..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/ImpexHighlighterService.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of "hybris integration" plugin for Intellij IDEA.
- * Copyright (C) 2019 EPAM Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.intellij.idea.plugin.hybris.impex.assistance;
-
-import com.intellij.openapi.editor.Editor;
-
-interface ImpexHighlighterService {
-
- fun highlight(editor: Editor)
-
- fun releaseEditorData(editor: Editor)
-}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexColumnHighlightingCaretListener.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexColumnHighlightingCaretListener.kt
deleted file mode 100644
index 2864b8668..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexColumnHighlightingCaretListener.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2019-2023 EPAM Systems and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-package com.intellij.idea.plugin.hybris.impex.assistance.event
-
-import com.intellij.idea.plugin.hybris.common.services.CommonIdeaService
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexColumnHighlighterService
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.editor.event.CaretEvent
-import com.intellij.openapi.editor.event.CaretListener
-
-@Service
-class ImpexColumnHighlightingCaretListener : CaretListener {
-
- override fun caretPositionChanged(e: CaretEvent) {
- if (CommonIdeaService.instance.isTypingActionInProgress()) return
-
- ImpexColumnHighlighterService.instance.highlight(e.editor)
- }
-
- override fun caretAdded(e: CaretEvent) {}
- override fun caretRemoved(e: CaretEvent) {}
-
- companion object {
- val instance: ImpexColumnHighlightingCaretListener = ApplicationManager.getApplication().getService(ImpexColumnHighlightingCaretListener::class.java)
- }
-
-}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexEditorFactoryListener.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexEditorFactoryListener.kt
index 55171baf6..55c9b8784 100644
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexEditorFactoryListener.kt
+++ b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexEditorFactoryListener.kt
@@ -1,6 +1,6 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2019 EPAM Systems
+ * Copyright (C) 2019-2023 EPAM Systems and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -17,20 +17,25 @@
*/
package com.intellij.idea.plugin.hybris.impex.assistance.event
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexColumnHighlighterService
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexHeaderNameHighlighterService
import com.intellij.openapi.editor.event.EditorFactoryEvent
import com.intellij.openapi.editor.event.EditorFactoryListener
class ImpexEditorFactoryListener : EditorFactoryListener {
- private val impexColumnHighlighterService = ImpexColumnHighlighterService.instance
- private val impexHeaderNameHighlighterService = ImpexHeaderNameHighlighterService.instance
+ override fun editorCreated(editorFactoryEvent: EditorFactoryEvent) {
+ val editor = editorFactoryEvent.editor
- override fun editorCreated(editorFactoryEvent: EditorFactoryEvent) {}
+ with(ImpexHighlightingCaretListener.instance) {
+ editor.caretModel.addCaretListener(this)
+ }
+ }
override fun editorReleased(editorFactoryEvent: EditorFactoryEvent) {
- impexHeaderNameHighlighterService.releaseEditorData(editorFactoryEvent.editor)
- impexColumnHighlighterService.releaseEditorData(editorFactoryEvent.editor)
+ val editor = editorFactoryEvent.editor
+
+ with(ImpexHighlightingCaretListener.instance) {
+ this.clearHighlightedArea(editor)
+ editor.caretModel.removeCaretListener(this)
+ }
}
}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHeaderHighlightingCaretListener.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHeaderHighlightingCaretListener.kt
deleted file mode 100644
index 6593c294a..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHeaderHighlightingCaretListener.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2019-2023 EPAM Systems and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-package com.intellij.idea.plugin.hybris.impex.assistance.event
-
-import com.intellij.idea.plugin.hybris.common.services.CommonIdeaService
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexHeaderNameHighlighterService
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.editor.event.CaretEvent
-import com.intellij.openapi.editor.event.CaretListener
-
-@Service
-class ImpexHeaderHighlightingCaretListener : CaretListener {
-
- override fun caretPositionChanged(e: CaretEvent) {
- if (CommonIdeaService.instance.isTypingActionInProgress()) return
-
- ImpexHeaderNameHighlighterService.instance.highlight(e.editor)
- }
-
- override fun caretAdded(e: CaretEvent) {}
- override fun caretRemoved(e: CaretEvent) {}
-
- companion object {
- val instance: ImpexHeaderHighlightingCaretListener = ApplicationManager.getApplication().getService(ImpexHeaderHighlightingCaretListener::class.java)
- }
-
-}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHighlightingCaretListener.kt b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHighlightingCaretListener.kt
new file mode 100644
index 000000000..28b81d68c
--- /dev/null
+++ b/src/com/intellij/idea/plugin/hybris/impex/assistance/event/ImpexHighlightingCaretListener.kt
@@ -0,0 +1,161 @@
+/*
+ * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
+ * Copyright (C) 2019-2023 EPAM Systems and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+package com.intellij.idea.plugin.hybris.impex.assistance.event
+
+import com.intellij.codeInsight.folding.impl.FoldingUtil
+import com.intellij.codeInsight.highlighting.HighlightManager
+import com.intellij.codeInsight.highlighting.HighlightManagerImpl
+import com.intellij.codeInsight.highlighting.HighlightUsagesHandler
+import com.intellij.idea.plugin.hybris.common.services.CommonIdeaService
+import com.intellij.idea.plugin.hybris.impex.ImpexLanguage
+import com.intellij.idea.plugin.hybris.impex.psi.ImpexFullHeaderParameter
+import com.intellij.idea.plugin.hybris.impex.utils.ImpexPsiUtils
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.ModalityState
+import com.intellij.openapi.application.ReadAction
+import com.intellij.openapi.components.Service
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.editor.colors.EditorColors
+import com.intellij.openapi.editor.event.CaretEvent
+import com.intellij.openapi.editor.event.CaretListener
+import com.intellij.openapi.editor.markup.RangeHighlighter
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.TextRange
+import com.intellij.openapi.util.removeUserData
+import com.intellij.psi.PsiElement
+import com.intellij.psi.util.PsiUtilBase
+import com.intellij.util.concurrency.AppExecutorUtil
+
+@Service
+class ImpexHighlightingCaretListener : CaretListener {
+
+ override fun caretAdded(e: CaretEvent) {}
+ override fun caretRemoved(e: CaretEvent) {}
+
+ override fun caretPositionChanged(e: CaretEvent) {
+ if (CommonIdeaService.instance.isTypingActionInProgress()) return
+
+ val editor = e.editor
+ val project = editor.project ?: return
+ if (project.isDisposed) return
+
+ ReadAction
+ .nonBlocking> {
+ if (PsiUtilBase.getLanguageInEditor(editor, project) !is ImpexLanguage) return@nonBlocking emptyList()
+
+ ImpexPsiUtils.getHeaderOfValueGroupUnderCaret(editor)
+ ?.let { it as? ImpexFullHeaderParameter }
+ ?.let { listOf(it) }
+ ?: ImpexPsiUtils.getFullHeaderParameterUnderCaret(editor)
+ ?.valueGroups
+ ?.let { it.mapNotNull { ivg -> ivg.value } }
+ ?: emptyList()
+ }
+ .withDocumentsCommitted(project)
+ .expireWhen { editor.isDisposed }
+ .finishOnUiThread(ModalityState.defaultModalityState()) {
+ it.takeIf { it.isNotEmpty() }
+ ?.map { psiElement -> psiElement.textRange }
+ ?.filterNot { textRange -> FoldingUtil.isTextRangeFolded(editor, textRange) }
+ ?.let { textRanges -> highlightArea(editor, textRanges, project) }
+ ?: clearHighlightedArea(editor)
+ }
+ .submit(AppExecutorUtil.getAppExecutorService())
+ }
+
+ fun clearHighlightedArea(editor: Editor) {
+ editor.removeUserData(CACHE_KEY)
+ ?.let {
+ editor.project
+ ?.let { project -> modifyHighlightedArea(editor, it, project, true) }
+ }
+ }
+
+ private fun highlightArea(editor: Editor, values: List, project: Project) {
+ if (isAlreadyHighlighted(editor, values)) return
+
+ clearHighlightedArea(editor)
+
+ modifyHighlightedArea(editor, values, project, false)
+
+ editor.putUserData(CACHE_KEY, values)
+ }
+
+ private fun modifyHighlightedArea(
+ editor: Editor,
+ textRanges: List,
+ project: Project,
+ clear: Boolean
+ ) {
+ val highlightManager = HighlightManager.getInstance(project)
+ removeInvalidRangeHighlighters(editor, highlightManager)
+
+ // This list must be modifiable
+ // https://hybris-integration.atlassian.net/browse/IIP-11
+ textRanges
+ // Do not use Collectors.toList() here because:
+ // There are no guarantees on the type, mutability, serializability,
+ // or thread-safety of the List returned; if more control over the
+ // returned List is required, use toCollection(Supplier).
+ .toMutableList()
+ .takeIf { it.isNotEmpty() }
+ ?.let {
+ HighlightUsagesHandler.highlightRanges(
+ highlightManager,
+ editor,
+ EditorColors.SEARCH_RESULT_ATTRIBUTES,
+ clear,
+ it
+ )
+ }
+ }
+
+ /**
+ * IIPS-174: It seems like sometimes when we highlight code inside "Code Preview Panel" in combination with OOTB
+ * "unchanged lines" folding from IDEA it can end up in creating invalid highlighting ranges.
+ * E.g. when you run an inspection for an impex file and in the results panel click on an inspection result
+ * on the right it shows you a preview of a snippet from that file, and if you have multiple inspection warnings in
+ * the same file when you click on them the preview panel jumps into different parts of the file, which leads to
+ * creation of multiple highlight ranges while the editor stays the same, but OOTB folding messes everything up by
+ * folding many lines as the result highlight ranges created for the first inspection have invalid start and end
+ * offsets for the editor with folded lines when you click on some other inspection from the same file.
+ */
+ private fun removeInvalidRangeHighlighters(editor: Editor, highlightManager: HighlightManager) {
+ if (highlightManager !is HighlightManagerImpl) return
+
+ highlightManager.getHighlighters(editor)
+ .filter { isNotProperRangeHighlighter(it) }
+ .forEach { highlightManager.removeSegmentHighlighter(editor, it) }
+ }
+
+ /**
+ * From [TextRange#isProperRange(int, int))][TextRange.isProperRange]
+ */
+ private fun isNotProperRangeHighlighter(rangeHighlighter: RangeHighlighter) = rangeHighlighter.startOffset > rangeHighlighter.endOffset
+ || rangeHighlighter.startOffset < 0
+
+ private fun isAlreadyHighlighted(editor: Editor, ranges: List) = editor.getUserData(CACHE_KEY) == ranges
+
+ companion object {
+ private val CACHE_KEY = Key.create>("IMPEX_COLUMN_HIGHLIGHT_CACHE")
+
+ val instance: ImpexHighlightingCaretListener = ApplicationManager.getApplication().getService(ImpexHighlightingCaretListener::class.java)
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiManager.kt b/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiManager.kt
deleted file mode 100644
index 426901e2e..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiManager.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2019-2023 EPAM Systems and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-package com.intellij.idea.plugin.hybris.impex.psi
-
-import com.intellij.idea.plugin.hybris.impex.assistance.event.ImpexColumnHighlightingCaretListener
-import com.intellij.idea.plugin.hybris.impex.assistance.event.ImpexHeaderHighlightingCaretListener
-import com.intellij.openapi.Disposable
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.editor.EditorFactory
-
-@Service
-class ImpexPsiManager : Disposable {
-
- fun registerListeners() {
- with(EditorFactory.getInstance()) {
- this.eventMulticaster.addCaretListener(ImpexHeaderHighlightingCaretListener.instance, this@ImpexPsiManager)
- this.eventMulticaster.addCaretListener(ImpexColumnHighlightingCaretListener.instance, this@ImpexPsiManager)
- }
- }
-
- override fun dispose() = Unit
-
- companion object {
- val instance: ImpexPsiManager = ApplicationManager.getApplication().getService(ImpexPsiManager::class.java)
- }
-
-}
diff --git a/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiTreeChangeListener.kt b/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiTreeChangeListener.kt
deleted file mode 100644
index 4283e60d9..000000000
--- a/src/com/intellij/idea/plugin/hybris/impex/psi/ImpexPsiTreeChangeListener.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2023 EPAM Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-package com.intellij.idea.plugin.hybris.impex.psi
-
-import com.intellij.idea.plugin.hybris.impex.ImpexLanguage
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexColumnHighlighterService
-import com.intellij.idea.plugin.hybris.impex.assistance.ImpexHeaderNameHighlighterService
-import com.intellij.psi.PsiTreeChangeEvent
-import com.intellij.psi.PsiTreeChangeListener
-import com.intellij.psi.util.PsiEditorUtil
-import com.intellij.psi.util.PsiUtilBase
-
-class ImpexPsiTreeChangeListener : PsiTreeChangeListener {
-
- private fun highlightHeader(psiTreeChangeEvent: PsiTreeChangeEvent) {
- val file = psiTreeChangeEvent.file ?: return
- val editor = PsiEditorUtil.findEditor(file) ?: return
- val project = editor.project ?: return
- if (project.isDisposed) return
-
- if (PsiUtilBase.getLanguageInEditor(editor, project) is ImpexLanguage) {
- ImpexHeaderNameHighlighterService.instance.highlight(editor)
- ImpexColumnHighlighterService.instance.highlight(editor)
- }
- }
-
- override fun childAdded(psiTreeChangeEvent: PsiTreeChangeEvent) {
- highlightHeader(psiTreeChangeEvent)
- }
-
- override fun childRemoved(psiTreeChangeEvent: PsiTreeChangeEvent) {
- highlightHeader(psiTreeChangeEvent)
- }
-
- override fun childReplaced(psiTreeChangeEvent: PsiTreeChangeEvent) {
- highlightHeader(psiTreeChangeEvent)
- }
-
- override fun childMoved(psiTreeChangeEvent: PsiTreeChangeEvent) {
- highlightHeader(psiTreeChangeEvent)
- }
-
-
- override fun beforeChildAddition(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun beforeChildRemoval(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun beforeChildReplacement(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun beforeChildMovement(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun beforeChildrenChange(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun beforePropertyChange(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun childrenChanged(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
- override fun propertyChanged(psiTreeChangeEvent: PsiTreeChangeEvent) = Unit
-}
\ No newline at end of file
diff --git a/src/com/intellij/idea/plugin/hybris/impex/utils/ImpexPsiUtils.java b/src/com/intellij/idea/plugin/hybris/impex/utils/ImpexPsiUtils.java
index b2328f36b..443efbbc8 100644
--- a/src/com/intellij/idea/plugin/hybris/impex/utils/ImpexPsiUtils.java
+++ b/src/com/intellij/idea/plugin/hybris/impex/utils/ImpexPsiUtils.java
@@ -1,6 +1,7 @@
/*
- * This file is part of "hybris integration" plugin for Intellij IDEA.
+ * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2014-2016 Alexander Bartash
+ * Copyright (C) 2019-2023 EPAM Systems and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -310,6 +311,7 @@ public static PsiElement getPrevValueLine(@NotNull final PsiElement element) {
}
+ @Nullable
public static PsiElement getHeaderOfValueGroupUnderCaret(@NotNull final Editor editor) {
Validate.notNull(editor);
@@ -323,7 +325,8 @@ public static PsiElement getHeaderOfValueGroupUnderCaret(@NotNull final Editor e
return getHeaderForValueGroup(valueGroup);
}
- public static @Nullable ImpexFullHeaderParameter getFullHeaderParameterUnderCaret(@NotNull final Editor editor) {
+ @Nullable
+ public static ImpexFullHeaderParameter getFullHeaderParameterUnderCaret(@NotNull final Editor editor) {
final var psiElementUnderCaret = PsiUtilBase.getElementAtCaret(editor);
if (psiElementUnderCaret == null) return null;
diff --git a/src/com/intellij/idea/plugin/hybris/project/providers/HybrisWritingAccessProvider.java b/src/com/intellij/idea/plugin/hybris/project/providers/HybrisWritingAccessProvider.java
index b68fb3775..9c7e2950d 100644
--- a/src/com/intellij/idea/plugin/hybris/project/providers/HybrisWritingAccessProvider.java
+++ b/src/com/intellij/idea/plugin/hybris/project/providers/HybrisWritingAccessProvider.java
@@ -20,11 +20,9 @@
package com.intellij.idea.plugin.hybris.project.providers;
import com.intellij.idea.plugin.hybris.settings.HybrisProjectSettingsComponent;
-import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Key;
-import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.WritingAccessProvider;
import com.intellij.util.ObjectUtils;
@@ -97,15 +95,7 @@ protected boolean isFileReadOnly(@NotNull final VirtualFile file) {
return false;
}
- return Arrays.stream(ModuleManager.getInstance(myProject).getModules())
- .filter(module -> {
- for (final var contentRoot : ModuleRootManager.getInstance(module).getContentRoots()) {
- if (VfsUtilCore.isAncestor(contentRoot, file, false)) return true;
- }
- return false;
- }
- )
- .findFirst()
+ return Optional.ofNullable(ModuleUtil.findModuleForFile(file, myProject))
.map(module -> HybrisProjectSettingsComponent.getInstance(myProject)
.getModuleSettings(module)
.getReadonly()
@@ -114,7 +104,7 @@ protected boolean isFileReadOnly(@NotNull final VirtualFile file) {
}
private boolean isTemporarilyWritable(@NotNull final VirtualFile vFile) {
- Boolean excluded = vFile.getUserData(KEY_TEMPORARY_WRITABLE);
+ final Boolean excluded = vFile.getUserData(KEY_TEMPORARY_WRITABLE);
return excluded != null && excluded;
}
diff --git a/src/com/intellij/idea/plugin/hybris/startup/ImpexHeaderHighlighterStartupActivity.kt b/src/com/intellij/idea/plugin/hybris/startup/ImpexHeaderHighlighterStartupActivity.kt
deleted file mode 100644
index e3fff1210..000000000
--- a/src/com/intellij/idea/plugin/hybris/startup/ImpexHeaderHighlighterStartupActivity.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
- * Copyright (C) 2023 EPAM Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-package com.intellij.idea.plugin.hybris.startup
-
-import com.intellij.idea.plugin.hybris.impex.psi.ImpexPsiManager
-import com.intellij.idea.plugin.hybris.settings.HybrisProjectSettingsComponent
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.startup.ProjectActivity
-
-class ImpexHeaderHighlighterStartupActivity : ProjectActivity {
-
- override suspend fun execute(project: Project) {
- if (!HybrisProjectSettingsComponent.getInstance(project).isHybrisProject()) return
-
- ImpexPsiManager.instance.registerListeners();
- }
-}
\ No newline at end of file