mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
move goto base functionality from lang-impl to analysis-impl
GitOrigin-RevId: ac1c1c2d5e6ae6e71f628424179b2d50a04d79d0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1545256330
commit
606f7c9d61
@@ -0,0 +1,63 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtilKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class TargetElementUtilBase {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* identifiers around, or the {@code offset} is already in one.
|
||||
*
|
||||
* @param file language source for the {@link #isIdentifierPart(PsiFile, CharSequence, int)}
|
||||
* @see PsiTreeUtilKt#elementsAroundOffsetUp(PsiFile, int)
|
||||
*/
|
||||
public static int adjustOffset(@Nullable PsiFile file, Document document, final int offset) {
|
||||
CharSequence text = document.getCharsSequence();
|
||||
int correctedOffset = offset;
|
||||
int textLength = document.getTextLength();
|
||||
if (offset >= textLength) {
|
||||
correctedOffset = textLength - 1;
|
||||
}
|
||||
else if (!isIdentifierPart(file, text, offset)) {
|
||||
correctedOffset--;
|
||||
}
|
||||
if (correctedOffset >= 0) {
|
||||
char charAt = text.charAt(correctedOffset);
|
||||
if (charAt == '\'' || charAt == '"' || charAt == ')' || charAt == ']' ||
|
||||
isIdentifierPart(file, text, correctedOffset)) {
|
||||
return correctedOffset;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff character at the offset may be a part of an identifier.
|
||||
* @see Character#isJavaIdentifierPart(char)
|
||||
* @see TargetElementEvaluatorEx#isIdentifierPart(PsiFile, CharSequence, int)
|
||||
*/
|
||||
private static boolean isIdentifierPart(@Nullable PsiFile file, CharSequence text, int offset) {
|
||||
if (file != null) {
|
||||
TargetElementEvaluatorEx evaluator = getElementEvaluatorsEx(file.getLanguage());
|
||||
if (evaluator != null && evaluator.isIdentifierPart(file, text, offset)) return true;
|
||||
}
|
||||
return Character.isJavaIdentifierPart(text.charAt(offset));
|
||||
}
|
||||
|
||||
static final LanguageExtension<TargetElementEvaluator> TARGET_ELEMENT_EVALUATOR =
|
||||
new LanguageExtension<>("com.intellij.targetElementEvaluator");
|
||||
|
||||
@Nullable
|
||||
private static TargetElementEvaluatorEx getElementEvaluatorsEx(@NotNull Language language) {
|
||||
TargetElementEvaluator result = TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
return result instanceof TargetElementEvaluatorEx ? (TargetElementEvaluatorEx)result : null;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInsight.navigation.action;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler;
|
||||
import com.intellij.diagnostic.PluginException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class GotoDeclarationUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GotoDeclarationUtil.class);
|
||||
|
||||
@Nullable
|
||||
public static PsiElement[] findTargetElementsFromProviders(@NotNull Editor editor,
|
||||
int offset,
|
||||
PsiFile file) {
|
||||
PsiElement elementAt = file.findElementAt(TargetElementUtilBase.adjustOffset(file, editor.getDocument(), offset));
|
||||
for (GotoDeclarationHandler handler : GotoDeclarationHandler.EP_NAME.getExtensionList()) {
|
||||
PsiElement[] result = handler.getGotoDeclarationTargets(elementAt, offset, editor);
|
||||
if (result != null && result.length > 0) {
|
||||
return assertNotNullElements(result, handler.getClass()) ? result : null;
|
||||
}
|
||||
}
|
||||
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static boolean assertNotNullElements(@NotNull PsiElement[] result, Class<?> clazz) {
|
||||
for (PsiElement element : result) {
|
||||
if (element == null) {
|
||||
PluginException.logPluginError(LOG,
|
||||
"Null target element is returned by 'getGotoDeclarationTargets' in " + clazz.getName(), null, clazz
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ 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.lang.LanguageExtension;
|
||||
import com.intellij.navigation.NavigationItem;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -27,7 +26,6 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
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;
|
||||
@@ -110,7 +108,7 @@ public class TargetElementUtil {
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
PsiReference ref = file.findReferenceAt(adjustOffset(file, document, offset));
|
||||
PsiReference ref = file.findReferenceAt(TargetElementUtilBase.adjustOffset(file, document, offset));
|
||||
if (ref == null) return null;
|
||||
int elementOffset = ref.getElement().getTextRange().getStartOffset();
|
||||
|
||||
@@ -123,45 +121,8 @@ public class TargetElementUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* identifiers around, or the {@code offset} is already in one.
|
||||
*
|
||||
* @param file language source for the {@link #isIdentifierPart(com.intellij.psi.PsiFile, java.lang.CharSequence, int)}
|
||||
* @see PsiTreeUtilKt#elementsAroundOffsetUp(PsiFile, int)
|
||||
*/
|
||||
public static int adjustOffset(@Nullable PsiFile file, Document document, final int offset) {
|
||||
CharSequence text = document.getCharsSequence();
|
||||
int correctedOffset = offset;
|
||||
int textLength = document.getTextLength();
|
||||
if (offset >= textLength) {
|
||||
correctedOffset = textLength - 1;
|
||||
}
|
||||
else if (!isIdentifierPart(file, text, offset)) {
|
||||
correctedOffset--;
|
||||
}
|
||||
if (correctedOffset >= 0) {
|
||||
char charAt = text.charAt(correctedOffset);
|
||||
if (charAt == '\'' || charAt == '"' || charAt == ')' || charAt == ']' ||
|
||||
isIdentifierPart(file, text, correctedOffset)) {
|
||||
return correctedOffset;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true iff character at the offset may be a part of an identifier.
|
||||
* @see Character#isJavaIdentifierPart(char)
|
||||
* @see TargetElementEvaluatorEx#isIdentifierPart(com.intellij.psi.PsiFile, java.lang.CharSequence, int)
|
||||
*/
|
||||
private static boolean isIdentifierPart(@Nullable PsiFile file, CharSequence text, int offset) {
|
||||
if (file != null) {
|
||||
TargetElementEvaluatorEx evaluator = getElementEvaluatorsEx(file.getLanguage());
|
||||
if (evaluator != null && evaluator.isIdentifierPart(file, text, offset)) return true;
|
||||
}
|
||||
return Character.isJavaIdentifierPart(text.charAt(offset));
|
||||
return TargetElementUtilBase.adjustOffset(file, document, offset);
|
||||
}
|
||||
|
||||
public static boolean inVirtualSpace(@NotNull Editor editor, int offset) {
|
||||
@@ -225,7 +186,7 @@ public class TargetElementUtil {
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
int adjusted = adjustOffset(file, document, offset);
|
||||
int adjusted = TargetElementUtilBase.adjustOffset(file, document, offset);
|
||||
|
||||
PsiElement element = file.findElementAt(adjusted);
|
||||
if (BitUtil.isSet(flags, REFERENCED_ELEMENT_ACCEPTED)) {
|
||||
@@ -372,7 +333,7 @@ public class TargetElementUtil {
|
||||
if (ref == null) return null;
|
||||
|
||||
final Language language = ref.getElement().getLanguage();
|
||||
TargetElementEvaluator evaluator = TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
TargetElementEvaluator evaluator = TargetElementUtilBase.TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
if (evaluator != null) {
|
||||
final PsiElement element = evaluator.getElementByReference(ref, flags);
|
||||
if (element != null) return element;
|
||||
@@ -426,7 +387,7 @@ public class TargetElementUtil {
|
||||
}
|
||||
|
||||
public boolean includeSelfInGotoImplementation(@NotNull final PsiElement element) {
|
||||
TargetElementEvaluator evaluator = TARGET_ELEMENT_EVALUATOR.forLanguage(element.getLanguage());
|
||||
TargetElementEvaluator evaluator = TargetElementUtilBase.TARGET_ELEMENT_EVALUATOR.forLanguage(element.getLanguage());
|
||||
return evaluator == null || evaluator.includeSelfInGotoImplementation(element);
|
||||
}
|
||||
|
||||
@@ -445,16 +406,9 @@ public class TargetElementUtil {
|
||||
return PsiSearchHelper.getInstance(element.getProject()).getUseScope(file != null ? file : element);
|
||||
}
|
||||
|
||||
private static final LanguageExtension<TargetElementEvaluator> TARGET_ELEMENT_EVALUATOR =
|
||||
new LanguageExtension<>("com.intellij.targetElementEvaluator");
|
||||
@Nullable
|
||||
private static TargetElementEvaluatorEx getElementEvaluatorsEx(@NotNull Language language) {
|
||||
TargetElementEvaluator result = TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
return result instanceof TargetElementEvaluatorEx ? (TargetElementEvaluatorEx)result : null;
|
||||
}
|
||||
@Nullable
|
||||
private static TargetElementEvaluatorEx2 getElementEvaluatorsEx2(@NotNull Language language) {
|
||||
TargetElementEvaluator result = TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
TargetElementEvaluator result = TargetElementUtilBase.TARGET_ELEMENT_EVALUATOR.forLanguage(language);
|
||||
return result instanceof TargetElementEvaluatorEx2 ? (TargetElementEvaluatorEx2)result : null;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-22
@@ -8,7 +8,7 @@ import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil;
|
||||
import com.intellij.diagnostic.PluginException;
|
||||
import com.intellij.codeInsight.navigation.action.GotoDeclarationUtil;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.find.actions.ShowUsagesAction;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
@@ -241,7 +241,8 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
else {
|
||||
final TextRange range = reference.getRangeInElement();
|
||||
final String elementText = reference.getElement().getText();
|
||||
LOG.assertTrue(range.getStartOffset() >= 0 && range.getEndOffset() <= elementText.length(), Arrays.toString(elements) + ";" + reference);
|
||||
LOG.assertTrue(range.getStartOffset() >= 0 && range.getEndOffset() <= elementText.length(),
|
||||
Arrays.toString(elements) + ";" + reference);
|
||||
final String refText = range.substring(elementText);
|
||||
title = MessageFormat.format(titlePattern, refText);
|
||||
}
|
||||
@@ -302,15 +303,7 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (file == null) return null;
|
||||
|
||||
PsiElement elementAt = file.findElementAt(TargetElementUtil.adjustOffset(file, document, offset));
|
||||
for (GotoDeclarationHandler handler : GotoDeclarationHandler.EP_NAME.getExtensionList()) {
|
||||
PsiElement[] result = handler.getGotoDeclarationTargets(elementAt, offset, editor);
|
||||
if (result != null && result.length > 0) {
|
||||
return assertNotNullElements(result, handler.getClass()) ? result : null;
|
||||
}
|
||||
}
|
||||
|
||||
return PsiElement.EMPTY_ARRAY;
|
||||
return GotoDeclarationUtil.findTargetElementsFromProviders(editor, offset, file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -374,15 +367,4 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
return namesValidator.isKeyword(elementAtCaret.getText(), project);
|
||||
}
|
||||
|
||||
private static boolean assertNotNullElements(@NotNull PsiElement[] result, Class<?> clazz) {
|
||||
for (PsiElement element : result) {
|
||||
if (element == null) {
|
||||
PluginException.logPluginError(LOG,
|
||||
"Null target element is returned by 'getGotoDeclarationTargets' in " + clazz.getName(), null, clazz
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user