mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJ-CR-168801 [command-completion] IDEA-375698 Command completion. Highlight intention's scope
- use special range GitOrigin-RevId: d3fc41b6361f1d685c743d64a66637bf57bd38ea
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6e1e1dbf46
commit
b794b331f8
+3
-1
@@ -726,7 +726,9 @@ class JavaCommandsCompletionTest : LightFixtureCompletionTestCase() {
|
||||
myFixture.doHighlighting()
|
||||
myFixture.type(".")
|
||||
val elements = myFixture.completeBasic()
|
||||
selectItem(elements.first { element -> element.lookupString.contains("flip '=='", ignoreCase = true) })
|
||||
val item = elements.first { element -> element.lookupString.contains("flip '=='", ignoreCase = true) }
|
||||
assertEquals(TextRange(33, 37), (item.`as`(CommandCompletionLookupElement::class.java))?.highlighting?.range)
|
||||
selectItem(item)
|
||||
myFixture.checkResult("""
|
||||
class A {
|
||||
void foo() {
|
||||
|
||||
+17
-3
@@ -1,12 +1,14 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ig.fixes.braces;
|
||||
|
||||
import com.intellij.codeInsight.intention.CustomizableIntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.modcommand.ActionContext;
|
||||
import com.intellij.modcommand.ModCommandAction;
|
||||
import com.intellij.modcommand.Presentation;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.IGQuickFixesTestCase;
|
||||
@@ -49,11 +51,23 @@ public class SingleStatementInBlockFixTest extends IGQuickFixesTestCase {
|
||||
IntentionAction action = myFixture.findSingleIntention(getMessage("if"));
|
||||
ModCommandAction mcAction = action.asModCommandAction();
|
||||
assertNotNull(mcAction);
|
||||
PsiFile psiFile = myFixture.getFile();
|
||||
Presentation presentation =
|
||||
mcAction.getPresentation(ActionContext.from(myFixture.getEditor(), myFixture.getFile()));
|
||||
mcAction.getPresentation(ActionContext.from(myFixture.getEditor(), psiFile));
|
||||
assertNotNull(presentation);
|
||||
assertEquals(List.of(new Presentation.HighlightRange(TextRange.from(44, 1), EditorColors.DELETED_TEXT_ATTRIBUTES),
|
||||
new Presentation.HighlightRange(TextRange.from(87, 1), EditorColors.DELETED_TEXT_ATTRIBUTES)), presentation.rangesToHighlight());
|
||||
assertEquals(List.of(new Presentation.HighlightRange(TextRange.from(44, 1), Presentation.HighlightingKind.DELETED_RANGE),
|
||||
new Presentation.HighlightRange(TextRange.from(87, 1), Presentation.HighlightingKind.DELETED_RANGE)),
|
||||
presentation.rangesToHighlight());
|
||||
assertInstanceOf(action, CustomizableIntentionAction.class);
|
||||
List<CustomizableIntentionAction.RangeToHighlight> ranges =
|
||||
((CustomizableIntentionAction)action).getRangesToHighlight(myFixture.getEditor(), psiFile);
|
||||
assertSize(2, ranges);
|
||||
assertEquals(
|
||||
List.of(TextRange.from(44, 1), TextRange.from(87, 1)),
|
||||
List.of(ranges.get(0).getRangeInFile(), ranges.get(1).getRangeInFile()));
|
||||
assertEquals(
|
||||
List.of(EditorColors.DELETED_TEXT_ATTRIBUTES, EditorColors.DELETED_TEXT_ATTRIBUTES),
|
||||
List.of(ranges.get(0).getHighlightKey(), ranges.get(1).getHighlightKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2281,10 +2281,8 @@ f:com.intellij.modcommand.Presentation$FixAllOption
|
||||
- name():java.lang.String
|
||||
f:com.intellij.modcommand.Presentation$HighlightRange
|
||||
- java.lang.Record
|
||||
- <init>(com.intellij.openapi.util.TextRange,com.intellij.openapi.editor.colors.TextAttributesKey):V
|
||||
- f:equals(java.lang.Object):Z
|
||||
- f:hashCode():I
|
||||
- highlightKey():com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
- range():com.intellij.openapi.util.TextRange
|
||||
a:com.intellij.modcommand.PsiBasedModCommandAction
|
||||
- com.intellij.modcommand.ModCommandAction
|
||||
|
||||
@@ -632,6 +632,16 @@ com.intellij.modcommand.ModTemplateBuilder
|
||||
- a:field(com.intellij.psi.PsiElement,java.lang.String,java.lang.String,Z):com.intellij.modcommand.ModTemplateBuilder
|
||||
- a:finishAt(I):com.intellij.modcommand.ModTemplateBuilder
|
||||
- a:onTemplateFinished(java.util.function.Function):com.intellij.modcommand.ModTemplateBuilder
|
||||
f:com.intellij.modcommand.Presentation$HighlightRange
|
||||
- <init>(com.intellij.openapi.util.TextRange,com.intellij.modcommand.Presentation$HighlightingKind):V
|
||||
- highlightingKind():com.intellij.modcommand.Presentation$HighlightingKind
|
||||
e:com.intellij.modcommand.Presentation$HighlightingKind
|
||||
- java.lang.Enum
|
||||
- sf:AFFECTED_RANGE:com.intellij.modcommand.Presentation$HighlightingKind
|
||||
- sf:APPLICABLE_TO_RANGE:com.intellij.modcommand.Presentation$HighlightingKind
|
||||
- sf:DELETED_RANGE:com.intellij.modcommand.Presentation$HighlightingKind
|
||||
- s:valueOf(java.lang.String):com.intellij.modcommand.Presentation$HighlightingKind
|
||||
- s:values():com.intellij.modcommand.Presentation$HighlightingKind[]
|
||||
com.intellij.openapi.actionSystem.ShortcutProvider
|
||||
- a:getShortcut():com.intellij.openapi.actionSystem.ShortcutSet
|
||||
com.intellij.openapi.application.WriteActionAware
|
||||
|
||||
+1
@@ -115,6 +115,7 @@ public interface CustomizableIntentionAction extends IntentionAction {
|
||||
return psi.getContainingFile();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextAttributesKey getHighlightKey() {
|
||||
return highlightKey;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.intellij.openapi.command.undo.UndoUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.diagnostic.ReportingClassSubstitutor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.PossiblyDumbAware;
|
||||
@@ -282,7 +284,10 @@ public final class QuickFixWrapper implements IntentionAction, PriorityAction, C
|
||||
List<RangeToHighlight> highlight = myFix.getRangesToHighlight(context.project(), myDescriptor);
|
||||
if (!highlight.isEmpty()) {
|
||||
Presentation.HighlightRange[] ranges = ContainerUtil.map2Array(highlight, Presentation.HighlightRange.class,
|
||||
r -> new Presentation.HighlightRange(r.getRangeInFile(), r.getHighlightKey()));
|
||||
r -> {
|
||||
return new Presentation.HighlightRange(r.getRangeInFile(),
|
||||
convertToHighlightingType(r.getHighlightKey()));
|
||||
});
|
||||
presentation = presentation.withHighlighting(ranges);
|
||||
}
|
||||
if (myFix instanceof Iconable iconable) {
|
||||
@@ -294,6 +299,17 @@ public final class QuickFixWrapper implements IntentionAction, PriorityAction, C
|
||||
return presentation;
|
||||
}
|
||||
|
||||
private static @NotNull Presentation.HighlightingKind convertToHighlightingType(@NotNull TextAttributesKey key) {
|
||||
if (key == EditorColors.SEARCH_RESULT_ATTRIBUTES) {
|
||||
return Presentation.HighlightingKind.AFFECTED_RANGE;
|
||||
}
|
||||
else if (key == EditorColors.DELETED_TEXT_ATTRIBUTES) {
|
||||
return Presentation.HighlightingKind.DELETED_RANGE;
|
||||
}
|
||||
//just fallback to the default highlighting type
|
||||
return Presentation.HighlightingKind.AFFECTED_RANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ModCommand perform(@NotNull ActionContext context) {
|
||||
return myFix.perform(context.project(), myDescriptor);
|
||||
|
||||
@@ -4,8 +4,6 @@ package com.intellij.modcommand;
|
||||
import com.intellij.analysis.AnalysisBundle;
|
||||
import com.intellij.codeInsight.intention.PriorityAction;
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -82,7 +80,7 @@ public record Presentation(
|
||||
|
||||
public @NotNull Presentation withHighlighting(@NotNull TextRange @NotNull ... ranges) {
|
||||
List<HighlightRange> highlightRanges =
|
||||
ContainerUtil.map(ranges, r -> new HighlightRange(r, EditorColors.SEARCH_RESULT_ATTRIBUTES));
|
||||
ContainerUtil.map(ranges, r -> new HighlightRange(r, HighlightingKind.AFFECTED_RANGE));
|
||||
return new Presentation(name, priority, highlightRanges, icon, fixAllOption);
|
||||
}
|
||||
|
||||
@@ -103,10 +101,20 @@ public record Presentation(
|
||||
* Represents a tuple of a TextRange and TextAttributesKey used for highlighting a specific range of text.
|
||||
*
|
||||
* @param range The TextRange to be highlighted.
|
||||
* @param highlightKey The TextAttributesKey to be used for highlighting the range.
|
||||
* @param highlightingKind The kind of highlighting. It is used to determine TextAttributesKey or special ranges used for highlighting.
|
||||
*/
|
||||
public record HighlightRange(
|
||||
@NotNull TextRange range,
|
||||
@NotNull TextAttributesKey highlightKey
|
||||
@NotNull HighlightingKind highlightingKind
|
||||
) {}
|
||||
|
||||
public enum HighlightingKind {
|
||||
|
||||
AFFECTED_RANGE,
|
||||
DELETED_RANGE,
|
||||
/**
|
||||
* special range to define scope of applicability
|
||||
*/
|
||||
APPLICABLE_TO_RANGE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -56,11 +58,26 @@ public abstract class PsiBasedModCommandAction<E extends PsiElement> implements
|
||||
@Override
|
||||
public final @Nullable Presentation getPresentation(@NotNull ActionContext context) {
|
||||
E element = getElement(context);
|
||||
return element == null ? null : getPresentation(context, element);
|
||||
if (element == null) return null;
|
||||
Presentation presentation = getPresentation(context, element);
|
||||
return addApplicableRange(presentation, context, element);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @Nullable E getElement(@NotNull ActionContext context) {
|
||||
private @Nullable Presentation addApplicableRange(@Nullable Presentation presentation,
|
||||
@NotNull ActionContext context,
|
||||
@NotNull E element) {
|
||||
if (presentation == null) return null;
|
||||
//applicable range is used only inside the file where the action is called,
|
||||
//otherwise it can cause ast loading
|
||||
if (context.file() != element.getContainingFile()) {
|
||||
return presentation;
|
||||
}
|
||||
List<Presentation.HighlightRange> ranges = new ArrayList<>(presentation.rangesToHighlight());
|
||||
ranges.add(new Presentation.HighlightRange(element.getTextRange(), Presentation.HighlightingKind.APPLICABLE_TO_RANGE));
|
||||
return presentation.withHighlighting(ranges.toArray(Presentation.HighlightRange[]::new));
|
||||
}
|
||||
|
||||
private @Nullable E getElement(@NotNull ActionContext context) {
|
||||
if (myPointer != null) {
|
||||
E element = myPointer.getElement();
|
||||
if (element == null) return null;
|
||||
|
||||
+12
-2
@@ -10,6 +10,7 @@ import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
|
||||
import com.intellij.modcommand.*;
|
||||
import com.intellij.openapi.diagnostic.ReportingClassSubstitutor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.PossiblyDumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -115,9 +116,18 @@ public final class ModCommandActionWrapper implements IntentionAction, PriorityA
|
||||
@Override
|
||||
public @Unmodifiable @NotNull List<RangeToHighlight> getRangesToHighlight(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
if (myPresentation == null) return List.of();
|
||||
return ContainerUtil.map(myPresentation.rangesToHighlight(), range -> new RangeToHighlight(file, range.range(), range.highlightKey()));
|
||||
return ContainerUtil.mapNotNull(myPresentation.rangesToHighlight(), range -> convertToRangeToHighlight(file, range));
|
||||
}
|
||||
|
||||
|
||||
private static @Nullable RangeToHighlight convertToRangeToHighlight(@NotNull PsiFile file, @Nullable Presentation.HighlightRange range) {
|
||||
if (range == null) return null;
|
||||
return switch (range.highlightingKind()) {
|
||||
case AFFECTED_RANGE -> new RangeToHighlight(file, range.range(), EditorColors.SEARCH_RESULT_ATTRIBUTES);
|
||||
case DELETED_RANGE -> new RangeToHighlight(file, range.range(), EditorColors.DELETED_TEXT_ATTRIBUTES);
|
||||
case APPLICABLE_TO_RANGE -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean belongsToMyFamily(@NotNull IntentionActionWithFixAllOption action) {
|
||||
ModCommandAction unwrapped = action.asModCommandAction();
|
||||
|
||||
+8
-4
@@ -30,6 +30,7 @@ import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.lang.annotation.HighlightSeverity.INFORMATION
|
||||
import com.intellij.lang.injection.InjectedLanguageManager
|
||||
import com.intellij.modcommand.ActionContext
|
||||
import com.intellij.modcommand.Presentation
|
||||
import com.intellij.modcommand.PsiBasedModCommandAction
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.readAction
|
||||
@@ -469,10 +470,13 @@ internal class DirectIntentionCommandProvider : CommandProvider {
|
||||
}
|
||||
val modCommandAction = intentionAction.asModCommandAction() ?: return null
|
||||
if (modCommandAction is PsiBasedModCommandAction<*>) {
|
||||
modCommandAction.getElement(ActionContext.from(editor, psiFile))?.let {
|
||||
return HighlightInfoLookup(it.textRange.intersection(TextRange(it.textRange.startOffset, currentOffset)),
|
||||
EditorColors.SEARCH_RESULT_ATTRIBUTES, 0)
|
||||
}
|
||||
modCommandAction.getPresentation(ActionContext.from(editor, psiFile))
|
||||
?.rangesToHighlight()
|
||||
?.firstOrNull { highlightRange -> highlightRange.highlightingKind() == Presentation.HighlightingKind.APPLICABLE_TO_RANGE }
|
||||
?.let {
|
||||
return HighlightInfoLookup(it.range().intersection(TextRange(it.range().startOffset, currentOffset)),
|
||||
EditorColors.SEARCH_RESULT_ATTRIBUTES, 0)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user