mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
LAB-31 introduce limited version of findTargetElement in TargetElementUtilBase (without lookup flag)
GitOrigin-RevId: 6501c5e7a06badaad410da0d87c74d49788c87a8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7d38f547aa
commit
7267c98c53
@@ -4,19 +4,22 @@ package com.intellij.codeInsight;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.PomDeclarationSearcher;
|
||||
import com.intellij.pom.PomTarget;
|
||||
import com.intellij.pom.PsiDeclaredTarget;
|
||||
import com.intellij.pom.references.PomService;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiFileSystemItem;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtilKt;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.indexing.DumbModeAccessType;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -26,6 +29,18 @@ import java.util.List;
|
||||
|
||||
public final class TargetElementUtilBase {
|
||||
|
||||
/**
|
||||
* A flag used in {@link #findTargetElement(Editor, int, int)} indicating that if a reference is found at the specified offset,
|
||||
* it should be resolved and the result returned.
|
||||
*/
|
||||
public static final int REFERENCED_ELEMENT_ACCEPTED = 0x01;
|
||||
|
||||
/**
|
||||
* A flag used in {@link #findTargetElement(Editor, int, int)} indicating that if a element declaration name (e.g. class name identifier)
|
||||
* is found at the specified offset, the declared element should be returned.
|
||||
*/
|
||||
public static final int ELEMENT_NAME_ACCEPTED = 0x02;
|
||||
|
||||
/**
|
||||
* Attempts to adjust the {@code offset} in the {@code file} to point to an {@link #isIdentifierPart(PsiFile, CharSequence, int) identifier},
|
||||
* single quote, double quote, closing bracket or parentheses by moving it back by a single character. Does nothing if there are no
|
||||
@@ -141,4 +156,138 @@ public final class TargetElementUtilBase {
|
||||
|
||||
return getNamedElement(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement doGetReferenceOrReferencedElement(@NotNull Editor editor, int flags, int offset) {
|
||||
PsiReference ref = findReference(editor, offset);
|
||||
if (ref == null) return null;
|
||||
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
PsiElement[] result = {null};
|
||||
FileBasedIndex.getInstance().ignoreDumbMode(() -> {
|
||||
final Language language = ref.getElement().getLanguage();
|
||||
TargetElementEvaluator evaluator = TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
if (evaluator != null) {
|
||||
final PsiElement element = evaluator.getElementByReference(ref, flags);
|
||||
if (element != null) {
|
||||
result[0] = element;
|
||||
return;
|
||||
}
|
||||
}
|
||||
result[0] = ref.resolve();
|
||||
}, project, DumbModeAccessType.RELIABLE_DATA_ONLY);
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiReference findReference(@NotNull Editor editor, int offset) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
|
||||
Document document = editor.getDocument();
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
PsiReference ref = file.findReferenceAt(adjustOffset(file, document, offset));
|
||||
if (ref == null) return null;
|
||||
int elementOffset = ref.getElement().getTextRange().getStartOffset();
|
||||
|
||||
for (TextRange range : ReferenceRange.getRanges(ref)) {
|
||||
if (range.shiftRight(elementOffset).containsOffset(offset)) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getReferenceOrReferencedElement(@NotNull PsiFile file, @NotNull Editor editor, int flags, int offset) {
|
||||
PsiElement result = doGetReferenceOrReferencedElement(editor, flags, offset);
|
||||
PsiElement languageElement = file.findElementAt(offset);
|
||||
Language language = languageElement != null ? languageElement.getLanguage() : file.getLanguage();
|
||||
TargetElementEvaluatorEx2 evaluator = getElementEvaluatorsEx2(language);
|
||||
if (evaluator != null) {
|
||||
result = evaluator.adjustReferenceOrReferencedElement(file, editor, offset, flags, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement doFindTargetElement(@NotNull Editor editor, int flags, int offset) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
|
||||
Document document = editor.getDocument();
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
int adjusted = adjustOffset(file, document, offset);
|
||||
|
||||
PsiElement element = file.findElementAt(adjusted);
|
||||
if (BitUtil.isSet(flags, REFERENCED_ELEMENT_ACCEPTED)) {
|
||||
final PsiElement referenceOrReferencedElement = getReferenceOrReferencedElement(file, editor, flags, offset);
|
||||
//if (referenceOrReferencedElement == null) {
|
||||
// return getReferenceOrReferencedElement(file, editor, flags, offset);
|
||||
//}
|
||||
if (isAcceptableReferencedElement(element, referenceOrReferencedElement)) {
|
||||
return referenceOrReferencedElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (element == null) return null;
|
||||
|
||||
if (BitUtil.isSet(flags, ELEMENT_NAME_ACCEPTED)) {
|
||||
if (element instanceof PsiNamedElement) return element;
|
||||
return getNamedElement(element, adjusted - element.getTextRange().getStartOffset());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isAcceptableReferencedElement(@Nullable PsiElement element, @Nullable PsiElement referenceOrReferencedElement) {
|
||||
if (referenceOrReferencedElement == null || !referenceOrReferencedElement.isValid()) return false;
|
||||
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
ThreeState answer = evaluator.isAcceptableReferencedElement(element, referenceOrReferencedElement);
|
||||
if (answer == ThreeState.YES) return true;
|
||||
if (answer == ThreeState.NO) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: this method can perform slow PSI activity (e.g. {@link PsiReference#resolve()}, so please avoid calling it from Swing thread.
|
||||
*
|
||||
* @param editor editor
|
||||
* @param flags a combination of {@link #REFERENCED_ELEMENT_ACCEPTED}, {@link #ELEMENT_NAME_ACCEPTED}
|
||||
* @return a PSI element declared or referenced at the specified offset in the editor, depending on the flags passed.
|
||||
* @see #findTargetElement(Editor, int, int)
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement findTargetElement(Editor editor, int flags) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
return findTargetElement(editor, flags, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: this method can perform slow PSI activity (e.g. {@link PsiReference#resolve()}, so please avoid calling it from Swing thread.
|
||||
* @param editor editor
|
||||
* @param flags a combination of {@link #REFERENCED_ELEMENT_ACCEPTED}, {@link #ELEMENT_NAME_ACCEPTED}
|
||||
* @param offset offset in the editor's document
|
||||
* @return a PSI element declared or referenced at the specified offset in the editor, depending on the flags passed.
|
||||
* @see #findTargetElement(Editor, int)
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement findTargetElement(@NotNull Editor editor, int flags, int offset) {
|
||||
PsiElement result = doFindTargetElement(editor, flags, offset);
|
||||
TargetElementEvaluatorEx2 evaluator = result != null ? getElementEvaluatorsEx2(result.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
result = evaluator.adjustTargetElement(editor, offset, flags, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.ide.util.EditSourceUtil;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -16,15 +15,11 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.BitUtil;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.indexing.DumbModeAccessType;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -37,16 +32,14 @@ import java.util.List;
|
||||
|
||||
public class TargetElementUtil {
|
||||
/**
|
||||
* A flag used in {@link #findTargetElement(Editor, int, int)} indicating that if a reference is found at the specified offset,
|
||||
* it should be resolved and the result returned.
|
||||
* @see TargetElementUtilBase#REFERENCED_ELEMENT_ACCEPTED
|
||||
*/
|
||||
public static final int REFERENCED_ELEMENT_ACCEPTED = 0x01;
|
||||
public static final int REFERENCED_ELEMENT_ACCEPTED = TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED;
|
||||
|
||||
/**
|
||||
* A flag used in {@link #findTargetElement(Editor, int, int)} indicating that if a element declaration name (e.g. class name identifier)
|
||||
* is found at the specified offset, the declared element should be returned.
|
||||
* @see TargetElementUtilBase#ELEMENT_NAME_ACCEPTED
|
||||
*/
|
||||
public static final int ELEMENT_NAME_ACCEPTED = 0x02;
|
||||
public static final int ELEMENT_NAME_ACCEPTED = TargetElementUtilBase.ELEMENT_NAME_ACCEPTED;
|
||||
|
||||
/**
|
||||
* A flag used in {@link #findTargetElement(Editor, int, int)} indicating that if a lookup (e.g. completion) is shown in the editor,
|
||||
@@ -97,24 +90,7 @@ public class TargetElementUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiReference findReference(@NotNull Editor editor, int offset) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
|
||||
Document document = editor.getDocument();
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
PsiReference ref = file.findReferenceAt(TargetElementUtilBase.adjustOffset(file, document, offset));
|
||||
if (ref == null) return null;
|
||||
int elementOffset = ref.getElement().getTextRange().getStartOffset();
|
||||
|
||||
for (TextRange range : ReferenceRange.getRanges(ref)) {
|
||||
if (range.shiftRight(elementOffset).containsOffset(offset)) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return TargetElementUtilBase.findReference(editor, offset);
|
||||
}
|
||||
|
||||
public static int adjustOffset(@Nullable PsiFile file, Document document, final int offset) {
|
||||
@@ -158,16 +134,6 @@ public class TargetElementUtil {
|
||||
*/
|
||||
@Nullable
|
||||
public PsiElement findTargetElement(@NotNull Editor editor, int flags, int offset) {
|
||||
PsiElement result = doFindTargetElement(editor, flags, offset);
|
||||
TargetElementEvaluatorEx2 evaluator = result != null ? TargetElementUtilBase.getElementEvaluatorsEx2(result.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
result = evaluator.adjustTargetElement(editor, offset, flags, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiElement doFindTargetElement(@NotNull Editor editor, int flags, int offset) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
|
||||
@@ -178,30 +144,7 @@ public class TargetElementUtil {
|
||||
}
|
||||
}
|
||||
|
||||
Document document = editor.getDocument();
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
int adjusted = TargetElementUtilBase.adjustOffset(file, document, offset);
|
||||
|
||||
PsiElement element = file.findElementAt(adjusted);
|
||||
if (BitUtil.isSet(flags, REFERENCED_ELEMENT_ACCEPTED)) {
|
||||
final PsiElement referenceOrReferencedElement = getReferenceOrReferencedElement(file, editor, flags, offset);
|
||||
//if (referenceOrReferencedElement == null) {
|
||||
// return getReferenceOrReferencedElement(file, editor, flags, offset);
|
||||
//}
|
||||
if (isAcceptableReferencedElement(element, referenceOrReferencedElement)) {
|
||||
return referenceOrReferencedElement;
|
||||
}
|
||||
}
|
||||
|
||||
if (element == null) return null;
|
||||
|
||||
if (BitUtil.isSet(flags, ELEMENT_NAME_ACCEPTED)) {
|
||||
if (element instanceof PsiNamedElement) return element;
|
||||
return getNamedElement(element, adjusted - element.getTextRange().getStartOffset());
|
||||
}
|
||||
return null;
|
||||
return TargetElementUtilBase.findTargetElement(editor, flags, offset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -219,19 +162,6 @@ public class TargetElementUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isAcceptableReferencedElement(@Nullable PsiElement element, @Nullable PsiElement referenceOrReferencedElement) {
|
||||
if (referenceOrReferencedElement == null || !referenceOrReferencedElement.isValid()) return false;
|
||||
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? TargetElementUtilBase.getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
ThreeState answer = evaluator.isAcceptableReferencedElement(element, referenceOrReferencedElement);
|
||||
if (answer == ThreeState.YES) return true;
|
||||
if (answer == ThreeState.NO) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustElement(final Editor editor, final int flags, @Nullable PsiElement element, @Nullable PsiElement contextElement) {
|
||||
PsiElement langElement = element == null ? contextElement : element;
|
||||
@@ -260,42 +190,6 @@ public class TargetElementUtil {
|
||||
return TargetElementUtilBase.getNamedElement(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getReferenceOrReferencedElement(@NotNull PsiFile file, @NotNull Editor editor, int flags, int offset) {
|
||||
PsiElement result = doGetReferenceOrReferencedElement(editor, flags, offset);
|
||||
PsiElement languageElement = file.findElementAt(offset);
|
||||
Language language = languageElement != null ? languageElement.getLanguage() : file.getLanguage();
|
||||
TargetElementEvaluatorEx2 evaluator = TargetElementUtilBase.getElementEvaluatorsEx2(language);
|
||||
if (evaluator != null) {
|
||||
result = evaluator.adjustReferenceOrReferencedElement(file, editor, offset, flags, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement doGetReferenceOrReferencedElement(@NotNull Editor editor, int flags, int offset) {
|
||||
PsiReference ref = findReference(editor, offset);
|
||||
if (ref == null) return null;
|
||||
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
PsiElement[] result = {null};
|
||||
FileBasedIndex.getInstance().ignoreDumbMode(() -> {
|
||||
final Language language = ref.getElement().getLanguage();
|
||||
TargetElementEvaluator evaluator = TargetElementUtilBase.TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
if (evaluator != null) {
|
||||
final PsiElement element = evaluator.getElementByReference(ref, flags);
|
||||
if (element != null) {
|
||||
result[0] = element;
|
||||
return;
|
||||
}
|
||||
}
|
||||
result[0] = ref.resolve();
|
||||
}, project, DumbModeAccessType.RELIABLE_DATA_ONLY);
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<PsiElement> getTargetCandidates(@NotNull PsiReference reference) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
|
||||
Reference in New Issue
Block a user