From 606f7c9d61e1ff314958085899dbe4e14daee02e Mon Sep 17 00:00:00 2001 From: hsestupin Date: Sat, 9 Nov 2019 21:51:33 +0100 Subject: [PATCH] move goto base functionality from lang-impl to analysis-impl GitOrigin-RevId: ac1c1c2d5e6ae6e71f628424179b2d50a04d79d0 --- .../codeInsight/TargetElementEvaluatorEx.java | 0 .../codeInsight/TargetElementUtilBase.java | 63 +++++++++++++++++++ .../action/GotoDeclarationUtil.java | 44 +++++++++++++ .../codeInsight/TargetElementUtil.java | 58 ++--------------- .../actions/GotoDeclarationAction.java | 26 ++------ 5 files changed, 117 insertions(+), 74 deletions(-) rename platform/{lang-impl => analysis-impl}/src/com/intellij/codeInsight/TargetElementEvaluatorEx.java (100%) create mode 100644 platform/analysis-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java create mode 100644 platform/analysis-impl/src/com/intellij/codeInsight/navigation/action/GotoDeclarationUtil.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementEvaluatorEx.java b/platform/analysis-impl/src/com/intellij/codeInsight/TargetElementEvaluatorEx.java similarity index 100% rename from platform/lang-impl/src/com/intellij/codeInsight/TargetElementEvaluatorEx.java rename to platform/analysis-impl/src/com/intellij/codeInsight/TargetElementEvaluatorEx.java diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java b/platform/analysis-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java new file mode 100644 index 000000000000..01e6ceb481c8 --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java @@ -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 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; + } +} diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/navigation/action/GotoDeclarationUtil.java b/platform/analysis-impl/src/com/intellij/codeInsight/navigation/action/GotoDeclarationUtil.java new file mode 100644 index 000000000000..a415e366f377 --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInsight/navigation/action/GotoDeclarationUtil.java @@ -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; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtil.java index 615d23ff312e..5246a8c2949a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtil.java @@ -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 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; } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java index 32cd5768689e..3230fce5c35e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java @@ -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; - } }