[java] IDEA-373841 Backward compatibility regression for java copy-paste

GitOrigin-RevId: 55b8b55ae5105e95530e7b727f5aed2f87e5638a
This commit is contained in:
Mikhail Pyltsin
2025-06-02 14:04:14 +02:00
committed by intellij-monorepo-bot
parent 93b987c157
commit f66a437ec8
4 changed files with 351 additions and 95 deletions

View File

@@ -0,0 +1,304 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.java.JavaBundle;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModCommand;
import com.intellij.modcommand.ModCommandExecutor;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.LightweightHint;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public abstract class AbstractJavaCopyPasteReferenceProcessor<TRef extends PsiElement> extends CopyPastePostProcessor<ReferenceTransferableData>
implements ReferenceCopyPasteProcessor {
private static final Logger LOG = Logger.getInstance(AbstractJavaCopyPasteReferenceProcessor.class);
@Override
public @NotNull List<ReferenceTransferableData> collectTransferableData(@NotNull PsiFile file,
@NotNull Editor editor,
int @NotNull [] startOffsets,
int @NotNull [] endOffsets) {
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.NO) {
return Collections.emptyList();
}
if (!(file instanceof PsiClassOwner)) {
return Collections.emptyList();
}
ArrayList<ReferenceData> array = new ArrayList<>();
int refOffset = 0; // this is an offset delta for conversion from absolute offset to an offset inside clipboard contents
for (int j = 0; j < startOffsets.length; j++) {
refOffset += startOffsets[j];
for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffsets[j], endOffsets[j])) {
addReferenceData(file, refOffset, element, array);
}
refOffset -= endOffsets[j] + 1; // 1 accounts for line break inserted between contents corresponding to different carets
}
if (array.isEmpty()) {
return Collections.emptyList();
}
return Collections.singletonList(new ReferenceTransferableData(array.toArray(new ReferenceData[0])));
}
protected abstract void addReferenceData(PsiFile file, int startOffset, PsiElement element, ArrayList<ReferenceData> to);
@Override
public @NotNull List<ReferenceTransferableData> extractTransferableData(@NotNull Transferable content) {
ReferenceTransferableData referenceData = null;
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE != CodeInsightSettings.NO) {
try {
DataFlavor flavor = ReferenceData.getDataFlavor();
if (flavor != null) {
referenceData = (ReferenceTransferableData)content.getTransferData(flavor);
}
}
catch (UnsupportedFlavorException | IOException ignored) {
}
}
if (referenceData != null) { // copy to prevent changing of original by convertLineSeparators
return Collections.singletonList(referenceData.clone());
}
return Collections.emptyList();
}
@Override
public void processTransferableData(@NotNull Project project,
@NotNull Editor editor,
@NotNull RangeMarker bounds,
int caretOffset,
@NotNull Ref<? super Boolean> indented, @NotNull List<? extends ReferenceTransferableData> values) {
if (DumbService.getInstance(project).isDumb()) {
return;
}
Document document = editor.getDocument();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (!(file instanceof PsiClassOwner)) {
return;
}
PsiDocumentManager.getInstance(project).commitAllDocuments();
assert values.size() == 1;
ReferenceData[] referenceData = values.get(0).getData();
TRef[] refs;
refs = ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.compute(
() -> findReferencesToRestore(file, bounds, referenceData)
), JavaBundle.message("progress.title.searching.references"), true, project);
if (refs == null) return;
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.ASK) {
askReferencesToRestore(project, refs, referenceData);
}
PsiDocumentManager.getInstance(project).commitAllDocuments();
ApplicationEx app = ApplicationManagerEx.getApplicationEx();
Consumer<ProgressIndicator> consumer = indicator -> {
Set<String> imported = new TreeSet<>();
createAndApplyRestoreReferencesFixWithModCommand(referenceData, refs, imported, editor, file);
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES && !imported.isEmpty()) {
Integer size = imported.size();
String notificationText = JavaBundle.message("copy.paste.reference.notification", size);
app.invokeLater(
() -> showHint(editor, notificationText, e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
reviewImports(project, file, imported);
}
}), ModalityState.nonModal(), __ -> editor.isDisposed());
}
};
consumer.accept(null);
}
private void createAndApplyRestoreReferencesFixWithModCommand(ReferenceData[] data,
TRef[] refs,
@NotNull Set<String> imported,
@NotNull Editor editor,
@NotNull PsiFile file) {
if (refs.length == 0) return;
Optional<TRef> ref1 = Arrays.stream(refs).filter(Objects::nonNull).findAny();
if (ref1.isEmpty()) return;
ActionContext context = ActionContext.from(editor, file).withOffset(ref1.get().getTextRange().getStartOffset());
ModCommandExecutor.executeInteractively(context,
JavaBundle.message("progress.title.searching.references"),
editor,
() -> {
return ModCommand.psiUpdate(context.file(), (e, updater) -> {
List<TRef> copies = ContainerUtil.map(refs, el -> updater.getWritable(el));
restoreReferences(data, copies, imported, updater);
});
});
}
protected abstract void removeImports(@NotNull PsiFile file, @NotNull Set<String> imports);
private void reviewImports(@NotNull Project project, @NotNull PsiFile file, @NotNull Set<String> importedClasses) {
RestoreReferencesDialog dialog = new RestoreReferencesDialog(project, ArrayUtil.toObjectArray(importedClasses), false);
dialog.setTitle(JavaBundle.message("dialog.import.on.paste.title3"));
dialog.setExplanation(JavaBundle.message("dialog.paste.on.import.text3"));
if (dialog.showAndGet()) {
Object[] selectedElements = dialog.getSelectedElements();
if (selectedElements.length > 0) {
WriteCommandAction.runWriteCommandAction(project, "", null, () ->
removeImports(file, Arrays.stream(selectedElements).map(o -> (String)o).collect(Collectors.toSet())));
}
}
}
protected static void addReferenceData(@NotNull PsiElement element,
@NotNull List<? super ReferenceData> array,
int startOffset,
@NotNull String qClassName,
@Nullable String staticMemberName) {
TextRange range = element.getTextRange();
array.add(
new ReferenceData(
range.getStartOffset() - startOffset,
range.getEndOffset() - startOffset,
qClassName, staticMemberName));
}
protected abstract TRef @NotNull [] findReferencesToRestore(@NotNull PsiFile file,
@NotNull RangeMarker bounds,
ReferenceData @NotNull [] referenceData);
protected static PsiElement resolveReferenceIgnoreOverriding(@NotNull PsiPolyVariantReference reference) {
PsiElement referent = reference.resolve();
if (referent == null) {
ResolveResult[] results = reference.multiResolve(true);
if (results.length > 0) {
referent = results[0].getElement();
}
}
return referent;
}
protected abstract void restoreReferences(ReferenceData @NotNull [] referenceData,
List<TRef> refs,
@NotNull Set<? super String> imported);
protected void restoreReferences(ReferenceData @NotNull [] referenceData,
List<TRef> refs,
@NotNull Set<? super String> imported,
@NotNull ModPsiUpdater updater) {
restoreReferences(referenceData, refs, imported);
}
private static void askReferencesToRestore(@NotNull Project project, PsiElement @NotNull [] refs,
ReferenceData @NotNull [] referenceData) {
PsiManager manager = PsiManager.getInstance(project);
ThrowableComputable<Pair<ArrayList<Object>, Object[]>, RuntimeException> computable = () -> {
ArrayList<Object> array = new ArrayList<>();
Object[] refObjects = new Object[refs.length];
for (int i = 0; i < referenceData.length; i++) {
PsiElement ref = refs[i];
if (ref != null) {
LOG.assertTrue(ref.isValid());
ReferenceData data = referenceData[i];
PsiClass refClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(data.qClassName, ref.getResolveScope());
if (refClass == null) continue;
Object refObject = refClass;
if (data.staticMemberName != null) {
//Show static members as Strings
refObject = refClass.getQualifiedName() + "." + data.staticMemberName;
}
refObjects[i] = refObject;
if (!array.contains(refObject)) {
array.add(refObject);
}
}
}
return new Pair<>(array, refObjects);
};
Pair<ArrayList<Object>, Object[]> context;
context = ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.compute(
computable
), JavaBundle.message("progress.title.searching.references"), true, project);
if (context == null) return;
ArrayList<Object> array = context.getFirst();
Object[] refObjects = context.getSecond();
if (array.isEmpty()) return;
Object[] selectedObjects = ArrayUtil.toObjectArray(array);
Arrays.sort(selectedObjects, (o1, o2) -> getFQName(o1).compareToIgnoreCase(getFQName(o2)));
RestoreReferencesDialog dialog = new RestoreReferencesDialog(project, selectedObjects);
dialog.show();
selectedObjects = dialog.getSelectedElements();
for (int i = 0; i < referenceData.length; i++) {
PsiElement ref = refs[i];
if (ref != null) {
PsiUtilCore.ensureValid(ref);
Object refObject = refObjects[i];
boolean found = false;
for (Object selected : selectedObjects) {
if (Comparing.equal(refObject, selected)) {
found = true;
break;
}
}
if (!found) {
refs[i] = null;
}
}
}
}
private static void showHint(@NotNull Editor editor,
@NotNull @NlsContexts.HintText String info,
@Nullable HyperlinkListener hyperlinkListener) {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(info, hyperlinkListener, null, null));
int flags = HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE;
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, flags, 0, false);
}
private static String getFQName(@NotNull Object element) {
return element instanceof PsiClass ? ((PsiClass)element).getQualifiedName() : (String)element;
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
@@ -7,13 +7,8 @@ import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.java.JavaBundle;
import com.intellij.modcommand.ActionContext;
import com.intellij.modcommand.ModCommand;
import com.intellij.modcommand.ModCommandExecutor;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.command.WriteCommandAction;
@@ -22,15 +17,16 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.LightweightHint;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,15 +40,17 @@ import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* @deprecated use {@link AbstractJavaCopyPasteReferenceProcessor}
*/
@SuppressWarnings("DuplicatedCode")
@Deprecated(forRemoval = true)
public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> extends CopyPastePostProcessor<ReferenceTransferableData>
implements ReferenceCopyPasteProcessor {
private static final Logger LOG = Logger.getInstance(CopyPasteReferenceProcessor.class);
@Override
public @NotNull List<ReferenceTransferableData> collectTransferableData(@NotNull PsiFile file,
@NotNull Editor editor,
int @NotNull [] startOffsets,
int @NotNull [] endOffsets) {
public @NotNull List<ReferenceTransferableData> collectTransferableData(@NotNull PsiFile file, @NotNull Editor editor, int @NotNull [] startOffsets, int @NotNull [] endOffsets) {
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.NO) {
return Collections.emptyList();
}
@@ -120,12 +118,7 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
PsiDocumentManager.getInstance(project).commitAllDocuments();
assert values.size() == 1;
ReferenceData[] referenceData = values.get(0).getData();
TRef[] refs;
refs = ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.compute(
() -> findReferencesToRestore(file, bounds, referenceData)
), JavaBundle.message("progress.title.searching.references"), true, project);
if (refs == null) return;
TRef[] refs = findReferencesToRestore(file, bounds, referenceData);
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.ASK) {
askReferencesToRestore(project, refs, referenceData);
}
@@ -133,10 +126,9 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
ApplicationEx app = ApplicationManagerEx.getApplicationEx();
Consumer<ProgressIndicator> consumer = indicator -> {
Set<String> imported = new TreeSet<>();
createAndApplyRestoreReferencesFixWithModCommand(referenceData, refs, imported, editor, file);
restoreReferences(referenceData, refs, imported);
if (CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE == CodeInsightSettings.YES && !imported.isEmpty()) {
Integer size = imported.size();
String notificationText = JavaBundle.message("copy.paste.reference.notification", size);
String notificationText = JavaBundle.message("copy.paste.reference.notification", imported.size());
app.invokeLater(
() -> showHint(editor, notificationText, e -> {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
@@ -145,27 +137,8 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
}), ModalityState.nonModal(), __ -> editor.isDisposed());
}
};
consumer.accept(null);
}
private void createAndApplyRestoreReferencesFixWithModCommand(ReferenceData[] data,
TRef[] refs,
@NotNull Set<String> imported,
@NotNull Editor editor,
@NotNull PsiFile file) {
if (refs.length == 0) return;
Optional<TRef> ref1 = Arrays.stream(refs).filter(Objects::nonNull).findAny();
if (ref1.isEmpty()) return;
ActionContext context = ActionContext.from(editor, file).withOffset(ref1.get().getTextRange().getStartOffset());
ModCommandExecutor.executeInteractively(context,
JavaBundle.message("progress.title.searching.references"),
editor,
() -> {
return ModCommand.psiUpdate(context.file(), (e, updater) -> {
List<TRef> copies = ContainerUtil.map(refs, el -> updater.getWritable(el));
restoreReferences(data, copies, imported, updater);
});
});
app.runWriteActionWithCancellableProgressInDispatchThread(JavaBundle.message("progress.title.restore.references"), project, null, consumer);
}
protected abstract void removeImports(@NotNull PsiFile file, @NotNull Set<String> imports);
@@ -190,10 +163,10 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
@Nullable String staticMemberName) {
TextRange range = element.getTextRange();
array.add(
new ReferenceData(
range.getStartOffset() - startOffset,
range.getEndOffset() - startOffset,
qClassName, staticMemberName));
new ReferenceData(
range.getStartOffset() - startOffset,
range.getEndOffset() - startOffset,
qClassName, staticMemberName));
}
protected abstract TRef @NotNull [] findReferencesToRestore(@NotNull PsiFile file,
@@ -212,54 +185,35 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
}
protected abstract void restoreReferences(ReferenceData @NotNull [] referenceData,
List<TRef> refs,
TRef @NotNull [] refs,
@NotNull Set<? super String> imported);
protected void restoreReferences(ReferenceData @NotNull [] referenceData,
List<TRef> refs,
@NotNull Set<? super String> imported,
@NotNull ModPsiUpdater updater) {
restoreReferences(referenceData, refs, imported);
}
private static void askReferencesToRestore(@NotNull Project project, PsiElement @NotNull [] refs,
ReferenceData @NotNull [] referenceData) {
PsiManager manager = PsiManager.getInstance(project);
ThrowableComputable<Pair<ArrayList<Object>, Object[]>, RuntimeException> computable = () -> {
ArrayList<Object> array = new ArrayList<>();
Object[] refObjects = new Object[refs.length];
ArrayList<Object> array = new ArrayList<>();
Object[] refObjects = new Object[refs.length];
for (int i = 0; i < referenceData.length; i++) {
PsiElement ref = refs[i];
if (ref != null) {
LOG.assertTrue(ref.isValid());
ReferenceData data = referenceData[i];
PsiClass refClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(data.qClassName, ref.getResolveScope());
if (refClass == null) continue;
for (int i = 0; i < referenceData.length; i++) {
PsiElement ref = refs[i];
if (ref != null) {
LOG.assertTrue(ref.isValid());
ReferenceData data = referenceData[i];
PsiClass refClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(data.qClassName, ref.getResolveScope());
if (refClass == null) continue;
Object refObject = refClass;
if (data.staticMemberName != null) {
//Show static members as Strings
refObject = refClass.getQualifiedName() + "." + data.staticMemberName;
}
refObjects[i] = refObject;
Object refObject = refClass;
if (data.staticMemberName != null) {
//Show static members as Strings
refObject = refClass.getQualifiedName() + "." + data.staticMemberName;
}
refObjects[i] = refObject;
if (!array.contains(refObject)) {
array.add(refObject);
}
if (!array.contains(refObject)) {
array.add(refObject);
}
}
return new Pair<>(array, refObjects);
};
Pair<ArrayList<Object>, Object[]> context;
context = ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.compute(
computable
), JavaBundle.message("progress.title.searching.references"), true, project);
if (context == null) return;
ArrayList<Object> array = context.getFirst();
Object[] refObjects = context.getSecond();
}
if (array.isEmpty()) return;
Object[] selectedObjects = ArrayUtil.toObjectArray(array);
@@ -288,17 +242,15 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
}
}
private static void showHint(@NotNull Editor editor,
@NotNull @NlsContexts.HintText String info,
@Nullable HyperlinkListener hyperlinkListener) {
private static void showHint(@NotNull Editor editor, @NotNull @NlsContexts.HintText String info, @Nullable HyperlinkListener hyperlinkListener) {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
LightweightHint hint = new LightweightHint(HintUtil.createInformationLabel(info, hyperlinkListener, null, null));
int flags = HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE;
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER, flags, 0, false);
}
private static String getFQName(@NotNull Object element) {
return element instanceof PsiClass ? ((PsiClass)element).getQualifiedName() : (String)element;
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
@@ -25,7 +25,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
public final class JavaCopyPasteReferenceProcessor extends CopyPasteReferenceProcessor<PsiJavaCodeReferenceElement> {
public final class JavaCopyPasteReferenceProcessor extends AbstractJavaCopyPasteReferenceProcessor<PsiJavaCodeReferenceElement> {
private static final Logger LOG = Logger.getInstance(JavaCopyPasteReferenceProcessor.class);
@Override

View File

@@ -1,7 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.groovy.editor;
import com.intellij.codeInsight.editorActions.CopyPasteReferenceProcessor;
import com.intellij.codeInsight.editorActions.AbstractJavaCopyPasteReferenceProcessor;
import com.intellij.codeInsight.editorActions.ReferenceData;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.RangeMarker;
@@ -23,7 +23,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public final class GroovyReferenceCopyPasteProcessor extends CopyPasteReferenceProcessor<GrReferenceElement> {
public final class GroovyReferenceCopyPasteProcessor extends AbstractJavaCopyPasteReferenceProcessor<GrReferenceElement> {
private static final Logger LOG = Logger.getInstance(GroovyReferenceCopyPasteProcessor.class);
@Override