mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
CPP-2814 Rearrange descriptors and avoid overriding of host-IDE components - part 2
* (Java)TargetElementUtil converted to evaluator
This commit is contained in:
@@ -34,52 +34,52 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TargetElementUtil extends TargetElementUtilBase {
|
||||
public class TargetElementUtil extends TargetElementEvaluatorEx2 implements TargetElementUtilExtender{
|
||||
public static final int NEW_AS_CONSTRUCTOR = 0x04;
|
||||
public static final int THIS_ACCEPTED = 0x10;
|
||||
public static final int SUPER_ACCEPTED = 0x20;
|
||||
|
||||
@Override
|
||||
public int getAllAccepted() {
|
||||
return super.getAllAccepted() | NEW_AS_CONSTRUCTOR | THIS_ACCEPTED | SUPER_ACCEPTED;
|
||||
public int getAdditionalAccepted() {
|
||||
return NEW_AS_CONSTRUCTOR | THIS_ACCEPTED | SUPER_ACCEPTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefinitionSearchFlags() {
|
||||
return super.getDefinitionSearchFlags() | THIS_ACCEPTED | SUPER_ACCEPTED;
|
||||
public int getAdditionalDefinitionSearchFlags() {
|
||||
return THIS_ACCEPTED | SUPER_ACCEPTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getReferenceSearchFlags() {
|
||||
return super.getReferenceSearchFlags() | NEW_AS_CONSTRUCTOR;
|
||||
public int getAdditionalReferenceSearchFlags() {
|
||||
return NEW_AS_CONSTRUCTOR;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement findTargetElement(@NotNull final Editor editor, final int flags, final int offset) {
|
||||
final PsiElement element = super.findTargetElement(editor, flags, offset);
|
||||
if (element instanceof PsiKeyword) {
|
||||
if (element.getParent() instanceof PsiThisExpression) {
|
||||
public PsiElement adjustTargetElement(Editor editor, int offset, int flags, @NotNull PsiElement targetElement) {
|
||||
if (targetElement instanceof PsiKeyword) {
|
||||
if (targetElement.getParent() instanceof PsiThisExpression) {
|
||||
if ((flags & THIS_ACCEPTED) == 0) return null;
|
||||
PsiType type = ((PsiThisExpression)element.getParent()).getType();
|
||||
PsiType type = ((PsiThisExpression)targetElement.getParent()).getType();
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
return ((PsiClassType)type).resolve();
|
||||
}
|
||||
|
||||
if (element.getParent() instanceof PsiSuperExpression) {
|
||||
if (targetElement.getParent() instanceof PsiSuperExpression) {
|
||||
if ((flags & SUPER_ACCEPTED) == 0) return null;
|
||||
PsiType type = ((PsiSuperExpression)element.getParent()).getType();
|
||||
PsiType type = ((PsiSuperExpression)targetElement.getParent()).getType();
|
||||
if (!(type instanceof PsiClassType)) return null;
|
||||
return ((PsiClassType)type).resolve();
|
||||
}
|
||||
}
|
||||
return element;
|
||||
return super.adjustTargetElement(editor, offset, flags, targetElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAcceptableReferencedElement(final PsiElement element, final PsiElement referenceOrReferencedElement) {
|
||||
return super.isAcceptableReferencedElement(element, referenceOrReferencedElement) &&
|
||||
!isEnumConstantReference(element, referenceOrReferencedElement);
|
||||
@NotNull
|
||||
public Answer isAcceptableReferencedElement(@NotNull final PsiElement element, final PsiElement referenceOrReferencedElement) {
|
||||
if (isEnumConstantReference(element, referenceOrReferencedElement)) return Answer.NO;
|
||||
return super.isAcceptableReferencedElement(element, referenceOrReferencedElement);
|
||||
}
|
||||
|
||||
private static boolean isEnumConstantReference(final PsiElement element, final PsiElement referenceOrReferencedElement) {
|
||||
@@ -89,10 +89,19 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
((PsiMethod)referenceOrReferencedElement).isConstructor();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected PsiElement getReferenceOrReferencedElement(PsiFile file, Editor editor, int flags, int offset) {
|
||||
PsiElement refElement = super.getReferenceOrReferencedElement(file, editor, flags, offset);
|
||||
@Override
|
||||
public PsiElement getElementByReference(@NotNull PsiReference ref, int flags) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement adjustReferenceOrReferencedElement(PsiFile file,
|
||||
Editor editor,
|
||||
int offset,
|
||||
int flags,
|
||||
@Nullable PsiElement refElement) {
|
||||
PsiReference ref = null;
|
||||
if (refElement == null) {
|
||||
ref = TargetElementUtilBase.findReference(editor, offset);
|
||||
@@ -144,45 +153,37 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
return refElement;
|
||||
return super.adjustReferenceOrReferencedElement(file, editor, offset, flags, refElement);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiElement getNamedElement(final PsiElement element) {
|
||||
public PsiElement getNamedElement(@NotNull final PsiElement element) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (element instanceof PsiIdentifier) {
|
||||
if (parent instanceof PsiClass && element.equals(((PsiClass)parent).getNameIdentifier())) {
|
||||
return parent;
|
||||
}
|
||||
else if (parent instanceof PsiVariable && element.equals(((PsiVariable)parent).getNameIdentifier())) {
|
||||
return parent;
|
||||
}
|
||||
else if (parent instanceof PsiMethod && element.equals(((PsiMethod)parent).getNameIdentifier())) {
|
||||
return parent;
|
||||
}
|
||||
else if (parent instanceof PsiLabeledStatement && element.equals(((PsiLabeledStatement)parent).getLabelIdentifier())) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
//TODO: Code below this comment is very similar to parent code. We probably need to use "super()" instead, to prevent copy/paste in inheritors
|
||||
else if ((parent = PsiTreeUtil.getParentOfType(element, PsiNamedElement.class, false)) != null) {
|
||||
// A bit hacky depends on navigation offset correctly overridden
|
||||
if (parent.getTextOffset() == element.getTextRange().getStartOffset() && !(parent instanceof XmlAttribute)
|
||||
&& !(parent instanceof PsiFile && InjectedLanguageManager.getInstance(parent.getProject()).isInjectedFragment((PsiFile)parent))) {
|
||||
if (parent instanceof PsiClass && element.equals(((PsiClass)parent).getNameIdentifier())
|
||||
|| parent instanceof PsiVariable && element.equals(((PsiVariable)parent).getNameIdentifier())
|
||||
|| parent instanceof PsiMethod && element.equals(((PsiMethod)parent).getNameIdentifier())
|
||||
|| parent instanceof PsiLabeledStatement && element.equals(((PsiLabeledStatement)parent).getLabelIdentifier())) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isAcceptableNamedParent(@NotNull PsiElement parent) {
|
||||
return !(parent instanceof XmlAttribute)
|
||||
&& !(parent instanceof PsiFile && InjectedLanguageManager.getInstance(parent.getProject()).isInjectedFragment((PsiFile)parent));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiReferenceExpression findReferenceExpression(Editor editor) {
|
||||
final PsiReference ref = findReference(editor);
|
||||
final PsiReference ref = TargetElementUtilBase.findReference(editor);
|
||||
return ref instanceof PsiReferenceExpression ? (PsiReferenceExpression)ref : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement adjustReference(@NotNull final PsiReference ref) {
|
||||
final PsiElement parent = ref.getElement().getParent();
|
||||
@@ -192,7 +193,7 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement adjustElement(final Editor editor, final int flags, final PsiElement element, final PsiElement contextElement) {
|
||||
public PsiElement adjustElement(Editor editor, int flags, @Nullable PsiElement element, @Nullable PsiElement contextElement) {
|
||||
if (element != null) {
|
||||
if (element instanceof PsiAnonymousClass) {
|
||||
return ((PsiAnonymousClass)element).getBaseClassType().resolve();
|
||||
@@ -212,9 +213,9 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PsiElement> getTargetCandidates(final PsiReference reference) {
|
||||
@Nullable
|
||||
public Collection<PsiElement> getTargetCandidates(@NotNull PsiReference reference) {
|
||||
PsiElement parent = reference.getElement().getParent();
|
||||
if (parent instanceof PsiMethodCallExpression || parent instanceof PsiNewExpression &&
|
||||
((PsiNewExpression)parent).getArrayDimensions().length == 0 &&
|
||||
@@ -251,12 +252,13 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getGotoDeclarationTarget(final PsiElement element, final PsiElement navElement) {
|
||||
@Nullable
|
||||
public PsiElement getGotoDeclarationTarget(@NotNull final PsiElement element, @Nullable final PsiElement navElement) {
|
||||
if (navElement == element && element instanceof PsiCompiledElement && element instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)element;
|
||||
if (method.isConstructor() && method.getParameterList().getParametersCount() == 0) {
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
PsiElement navClass = aClass.getNavigationElement();
|
||||
PsiElement navClass = aClass == null ? null : aClass.getNavigationElement();
|
||||
if (aClass != navClass) return navClass;
|
||||
}
|
||||
}
|
||||
@@ -272,7 +274,7 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptImplementationForReference(final PsiReference reference, final PsiElement element) {
|
||||
public boolean acceptImplementationForReference(@Nullable PsiReference reference, @NotNull PsiElement element) {
|
||||
if (reference instanceof PsiReferenceExpression && element instanceof PsiMember) {
|
||||
return getMemberClass(reference, element) != null;
|
||||
}
|
||||
@@ -317,8 +319,10 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SearchScope getSearchScope(Editor editor, PsiElement element) {
|
||||
@Nullable
|
||||
public SearchScope getSearchScope(Editor editor, @NotNull PsiElement element) {
|
||||
final PsiReferenceExpression referenceExpression = editor != null ? findReferenceExpression(editor) : null;
|
||||
if (referenceExpression != null && element instanceof PsiMethod) {
|
||||
final PsiClass[] memberClass = getMemberClass(referenceExpression, element);
|
||||
|
||||
+3
-3
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.concurrencyAnnotations;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -57,7 +57,7 @@ public class JCiPOrderEntryFix implements IntentionAction {
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
|
||||
if (!(file instanceof PsiJavaFile)) return false;
|
||||
|
||||
final PsiReference reference = TargetElementUtil.findReference(editor);
|
||||
final PsiReference reference = TargetElementUtilBase.findReference(editor);
|
||||
if (!(reference instanceof PsiJavaCodeReferenceElement)) return false;
|
||||
if (reference.resolve() != null) return false;
|
||||
@NonNls final String referenceName = ((PsiJavaCodeReferenceElement)reference).getReferenceName();
|
||||
@@ -74,7 +74,7 @@ public class JCiPOrderEntryFix implements IntentionAction {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
final PsiJavaCodeReferenceElement reference = (PsiJavaCodeReferenceElement)TargetElementUtil.findReference(editor);
|
||||
final PsiJavaCodeReferenceElement reference = (PsiJavaCodeReferenceElement)TargetElementUtilBase.findReference(editor);
|
||||
LOG.assertTrue(reference != null);
|
||||
String jarPath = PathUtil.getJarPathForClass(GuardedBy.class);
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
|
||||
+5
-5
@@ -16,7 +16,7 @@
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.codeInsight.TargetElementUtilBase
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
@@ -1107,17 +1107,17 @@ class Foo {
|
||||
type('x')
|
||||
assertContains 'x__foo', 'x__goo'
|
||||
edt {
|
||||
assert foo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
assert foo == TargetElementUtilBase.instance.findTargetElement(myFixture.editor, TargetElementUtilBase.LOOKUP_ITEM_ACCEPTED)
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN)
|
||||
assert goo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
assert goo == TargetElementUtilBase.instance.findTargetElement(myFixture.editor, TargetElementUtilBase.LOOKUP_ITEM_ACCEPTED)
|
||||
}
|
||||
|
||||
type('_')
|
||||
myFixture.assertPreferredCompletionItems 1, 'x__foo', 'x__goo'
|
||||
edt {
|
||||
assert goo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
assert goo == TargetElementUtilBase.instance.findTargetElement(myFixture.editor, TargetElementUtilBase.LOOKUP_ITEM_ACCEPTED)
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP)
|
||||
assert foo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
assert foo == TargetElementUtilBase.instance.findTargetElement(myFixture.editor, TargetElementUtilBase.LOOKUP_ITEM_ACCEPTED)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,77 @@
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class TargetElementEvaluatorEx2 implements TargetElementEvaluatorEx {
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class TargetElementEvaluatorEx2 implements TargetElementEvaluator {
|
||||
@Nullable
|
||||
public abstract PsiElement getNamedElement(@NotNull PsiElement element);
|
||||
public PsiElement getNamedElement(@NotNull PsiElement element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract boolean isAcceptableReferencedElement(@Nullable PsiElement element, @Nullable PsiElement referenceOrReferencedElement);
|
||||
public boolean isAcceptableNamedParent(@NotNull PsiElement parent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustElement(Editor editor, int flags, @Nullable PsiElement element, @Nullable PsiElement contextElement) {
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustTargetElement(Editor editor, int offset, int flags, @NotNull PsiElement targetElement) {
|
||||
return targetElement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustReferenceOrReferencedElement(PsiFile file,
|
||||
Editor editor,
|
||||
int offset,
|
||||
int flags,
|
||||
@Nullable PsiElement refElement) {
|
||||
return refElement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustReference(@NotNull PsiReference ref) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Collection<PsiElement> getTargetCandidates(@NotNull PsiReference reference) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getGotoDeclarationTarget(@NotNull final PsiElement element, @Nullable final PsiElement navElement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Answer isAcceptableReferencedElement(@NotNull PsiElement element, @Nullable PsiElement referenceOrReferencedElement) {
|
||||
return Answer.DEFAULT;
|
||||
}
|
||||
|
||||
public boolean includeSelfInGotoImplementation(@NotNull final PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean acceptImplementationForReference(@Nullable PsiReference reference, @NotNull PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SearchScope getSearchScope(Editor editor, @NotNull PsiElement element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum Answer { YES, NO, DEFAULT;}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actions.EditorActionUtil;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.pom.PomDeclarationSearcher;
|
||||
@@ -67,21 +67,33 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
|
||||
public int getAllAccepted() {
|
||||
return REFERENCED_ELEMENT_ACCEPTED | ELEMENT_NAME_ACCEPTED | LOOKUP_ITEM_ACCEPTED;
|
||||
int result = REFERENCED_ELEMENT_ACCEPTED | ELEMENT_NAME_ACCEPTED | LOOKUP_ITEM_ACCEPTED;
|
||||
for (TargetElementUtilExtender each : Extensions.getExtensions(TargetElementUtilExtender.EP_NAME)) {
|
||||
result |= each.getAdditionalAccepted();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts THIS or SUPER but not NEW_AS_CONSTRUCTOR.
|
||||
*/
|
||||
public int getDefinitionSearchFlags() {
|
||||
return getAllAccepted();
|
||||
int result = getAllAccepted();
|
||||
for (TargetElementUtilExtender each : Extensions.getExtensions(TargetElementUtilExtender.EP_NAME)) {
|
||||
result |= each.getAdditionalDefinitionSearchFlags();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts NEW_AS_CONSTRUCTOR but not THIS or SUPER.
|
||||
*/
|
||||
public int getReferenceSearchFlags() {
|
||||
return getAllAccepted();
|
||||
int result = getAllAccepted();
|
||||
for (TargetElementUtilExtender each : Extensions.getExtensions(TargetElementUtilExtender.EP_NAME)) {
|
||||
result |= each.getAdditionalReferenceSearchFlags();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -140,30 +152,12 @@ public class TargetElementUtilBase {
|
||||
|
||||
private static boolean isIdentifierPart(@Nullable PsiFile file, CharSequence text, int offset) {
|
||||
if (file != null) {
|
||||
for (TargetElementEvaluatorEx evaluator : getInstance().getElementEvaluatorsEx(file.getLanguage())) {
|
||||
if (evaluator instanceof TargetElementEvaluatorEx && ((TargetElementEvaluatorEx)evaluator).isIdentifierPart(file, text, offset)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TargetElementEvaluatorEx evaluator = getInstance().getElementEvaluatorsEx(file.getLanguage());
|
||||
if (evaluator != null && evaluator.isIdentifierPart(file, text, offset)) return true;
|
||||
}
|
||||
return Character.isJavaIdentifierPart(text.charAt(offset));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findTargetElement(Editor editor, int flags) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
final PsiElement result = getInstance().findTargetElement(editor, flags, editor.getCaretModel().getOffset());
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
final Integer offset = editor.getUserData(EditorActionUtil.EXPECTED_CARET_OFFSET);
|
||||
if (offset != null) {
|
||||
return getInstance().findTargetElement(editor, flags, offset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean inVirtualSpace(@NotNull Editor editor, int offset) {
|
||||
if (offset == editor.getCaretModel().getOffset()) {
|
||||
return EditorUtil.inVirtualSpace(editor, editor.getCaretModel().getLogicalPosition());
|
||||
@@ -172,8 +166,32 @@ public class TargetElementUtilBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findTargetElement(Editor editor, int flags) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
final PsiElement result = getInstance().findTargetElement(editor, flags, editor.getCaretModel().getOffset());
|
||||
if (result != null) return result;
|
||||
|
||||
final Integer offset = editor.getUserData(EditorActionUtil.EXPECTED_CARET_OFFSET);
|
||||
if (offset != null) {
|
||||
return getInstance().findTargetElement(editor, flags, offset);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public 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;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiElement doFindTargetElement(@NotNull Editor editor, int flags, int offset) {
|
||||
Project project = editor.getProject();
|
||||
if (project == null) return null;
|
||||
|
||||
@@ -229,25 +247,33 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
|
||||
protected boolean isAcceptableReferencedElement(@Nullable PsiElement element, @Nullable PsiElement referenceOrReferencedElement) {
|
||||
if (referenceOrReferencedElement != null && referenceOrReferencedElement.isValid()) return true;
|
||||
if (referenceOrReferencedElement == null || !referenceOrReferencedElement.isValid()) return false;
|
||||
|
||||
if (element != null) {
|
||||
for (TargetElementEvaluatorEx2 evaluator : getElementEvaluatorsEx2(element.getLanguage())) {
|
||||
if (evaluator.isAcceptableReferencedElement(element, referenceOrReferencedElement)) return true;
|
||||
}
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
TargetElementEvaluatorEx2.Answer answer = evaluator.isAcceptableReferencedElement(element, referenceOrReferencedElement);
|
||||
if (answer == TargetElementEvaluatorEx2.Answer.YES) return true;
|
||||
if (answer == TargetElementEvaluatorEx2.Answer.NO) return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustElement(final Editor editor, final int flags, final PsiElement element, final PsiElement contextElement) {
|
||||
public PsiElement adjustElement(final Editor editor, final int flags, @Nullable PsiElement element, @Nullable PsiElement contextElement) {
|
||||
PsiElement langElement = element == null ? contextElement : element;
|
||||
TargetElementEvaluatorEx2 evaluator = langElement != null ? getElementEvaluatorsEx2(langElement.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
element = evaluator.adjustElement(editor, flags, element, contextElement);
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement adjustReference(@NotNull PsiReference ref){
|
||||
return null;
|
||||
public PsiElement adjustReference(@NotNull PsiReference ref) {
|
||||
PsiElement element = ref.getElement();
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
return evaluator != null ? evaluator.adjustReference(ref) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -291,20 +317,22 @@ public class TargetElementUtilBase {
|
||||
|
||||
|
||||
@Nullable
|
||||
protected PsiElement getNamedElement(@Nullable final PsiElement element) {
|
||||
private PsiElement getNamedElement(@Nullable final PsiElement element) {
|
||||
if (element == null) return null;
|
||||
|
||||
for (TargetElementEvaluatorEx2 each : getElementEvaluatorsEx2(element.getLanguage())) {
|
||||
PsiElement result = each.getNamedElement(element);
|
||||
TargetElementEvaluatorEx2 evaluator = getElementEvaluatorsEx2(element.getLanguage());
|
||||
if (evaluator != null) {
|
||||
PsiElement result = evaluator.getNamedElement(element);
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
PsiElement parent;
|
||||
if ((parent = PsiTreeUtil.getParentOfType(element, PsiNamedElement.class, false)) != null) {
|
||||
// A bit hacky depends on navigation offset correctly overridden
|
||||
assert element != null : "notnull parent?";
|
||||
if (parent.getTextOffset() == element.getTextRange().getStartOffset()) {
|
||||
return parent;
|
||||
if (evaluator == null || evaluator.isAcceptableNamedParent(parent)) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,13 +340,25 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected PsiElement getReferenceOrReferencedElement(PsiFile file, Editor editor, int flags, int offset) {
|
||||
private PsiElement getReferenceOrReferencedElement(PsiFile file, Editor editor, int flags, int offset) {
|
||||
PsiElement result = doGetReferenceOrReferencedElement(file, 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 PsiElement doGetReferenceOrReferencedElement(PsiFile file, Editor editor, int flags, int offset) {
|
||||
PsiReference ref = findReference(editor, offset);
|
||||
if (ref == null) return null;
|
||||
|
||||
final Language language = ref.getElement().getLanguage();
|
||||
final List<TargetElementEvaluator> evaluators = targetElementEvaluator.allForLanguage(language);
|
||||
for (TargetElementEvaluator evaluator : evaluators) {
|
||||
TargetElementEvaluator evaluator = targetElementEvaluator.forLanguage(language);
|
||||
if (evaluator != null) {
|
||||
final PsiElement element = evaluator.getElementByReference(ref, flags);
|
||||
if (element != null) return element;
|
||||
}
|
||||
@@ -337,7 +377,14 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<PsiElement> getTargetCandidates(PsiReference reference) {
|
||||
public Collection<PsiElement> getTargetCandidates(@NotNull PsiReference reference) {
|
||||
PsiElement refElement = reference.getElement();
|
||||
TargetElementEvaluatorEx2 evaluator = refElement != null ? getElementEvaluatorsEx2(refElement.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
Collection<PsiElement> candidates = evaluator.getTargetCandidates(reference);
|
||||
if (candidates != null) return candidates;
|
||||
}
|
||||
|
||||
if (reference instanceof PsiPolyVariantReference) {
|
||||
final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false);
|
||||
List<PsiElement> navigatableResults = new ArrayList<PsiElement>(results.length);
|
||||
@@ -359,40 +406,40 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
|
||||
public PsiElement getGotoDeclarationTarget(final PsiElement element, final PsiElement navElement) {
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
if (evaluator != null) {
|
||||
PsiElement result = evaluator.getGotoDeclarationTarget(element, navElement);
|
||||
if (result != null) return result;
|
||||
}
|
||||
return navElement;
|
||||
}
|
||||
|
||||
public boolean includeSelfInGotoImplementation(@NotNull final PsiElement element) {
|
||||
final TargetElementEvaluator elementEvaluator = targetElementEvaluator.forLanguage(element.getLanguage());
|
||||
return elementEvaluator == null || elementEvaluator.includeSelfInGotoImplementation(element);
|
||||
TargetElementEvaluator evaluator = targetElementEvaluator.forLanguage(element.getLanguage());
|
||||
return evaluator == null || evaluator.includeSelfInGotoImplementation(element);
|
||||
}
|
||||
|
||||
public boolean acceptImplementationForReference(@Nullable PsiReference reference, @Nullable PsiElement element) {
|
||||
TargetElementEvaluatorEx2 evaluator = element != null ? getElementEvaluatorsEx2(element.getLanguage()) : null;
|
||||
return evaluator == null || evaluator.acceptImplementationForReference(reference, element);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SearchScope getSearchScope(Editor editor, @NotNull PsiElement element) {
|
||||
TargetElementEvaluatorEx2 evaluator = getElementEvaluatorsEx2(element.getLanguage());
|
||||
SearchScope result = evaluator != null ? evaluator.getSearchScope(editor, element) : null;
|
||||
return result != null ? result : PsiSearchHelper.SERVICE.getInstance(element.getProject()).getUseScope(element);
|
||||
}
|
||||
|
||||
protected final LanguageExtension<TargetElementEvaluator> targetElementEvaluator = new LanguageExtension<TargetElementEvaluator>("com.intellij.targetElementEvaluator");
|
||||
|
||||
private Iterable<TargetElementEvaluatorEx> getElementEvaluatorsEx(@NotNull Language language) {
|
||||
//noinspection unchecked
|
||||
return ContainerUtil.iterate(targetElementEvaluator.allForLanguage(language), new Condition() {
|
||||
@Override
|
||||
public boolean value(Object evaluator) {
|
||||
return evaluator instanceof TargetElementEvaluatorEx;
|
||||
}
|
||||
});
|
||||
@Nullable
|
||||
private TargetElementEvaluatorEx getElementEvaluatorsEx(@NotNull Language language) {
|
||||
TargetElementEvaluator result = targetElementEvaluator.forLanguage(language);
|
||||
return result instanceof TargetElementEvaluatorEx ? (TargetElementEvaluatorEx)result : null;
|
||||
}
|
||||
private Iterable<TargetElementEvaluatorEx2> getElementEvaluatorsEx2(@NotNull Language language) {
|
||||
//noinspection unchecked
|
||||
return ContainerUtil.iterate(targetElementEvaluator.allForLanguage(language), new Condition() {
|
||||
@Override
|
||||
public boolean value(Object evaluator) {
|
||||
return evaluator instanceof TargetElementEvaluatorEx2;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean acceptImplementationForReference(PsiReference reference, PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public SearchScope getSearchScope(Editor editor, PsiElement element) {
|
||||
return PsiSearchHelper.SERVICE.getInstance(element.getProject()).getUseScope(element);
|
||||
@Nullable
|
||||
private TargetElementEvaluatorEx2 getElementEvaluatorsEx2(@NotNull Language language) {
|
||||
TargetElementEvaluator result = targetElementEvaluator.forLanguage(language);
|
||||
return result instanceof TargetElementEvaluatorEx2 ? (TargetElementEvaluatorEx2)result : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
|
||||
public interface TargetElementUtilExtender {
|
||||
ExtensionPointName<TargetElementUtilExtender> EP_NAME = ExtensionPointName.create("com.intellij.targetElementUtilExtender");
|
||||
|
||||
int getAdditionalAccepted();
|
||||
|
||||
int getAdditionalDefinitionSearchFlags();
|
||||
|
||||
int getAdditionalReferenceSearchFlags();
|
||||
}
|
||||
@@ -720,6 +720,7 @@
|
||||
<extensionPoint name="templateCompletionProcessor"
|
||||
interface="com.intellij.codeInsight.template.macro.TemplateCompletionProcessor"/>
|
||||
|
||||
<extensionPoint name="targetElementUtilExtender" interface="com.intellij.codeInsight.TargetElementUtilExtender"/>
|
||||
<extensionPoint name="targetElementEvaluator" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.intellij.codeInsight.TargetElementEvaluator"/>
|
||||
</extensionPoint>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<orderEntry type="module" module-name="junit" scope="TEST" />
|
||||
<orderEntry type="module" module-name="java-indexing-api" />
|
||||
<orderEntry type="module" module-name="java-psi-impl" />
|
||||
<orderEntry type="module" module-name="java-impl" />
|
||||
<orderEntry type="module" module-name="core-impl" />
|
||||
<orderEntry type="module" module-name="extensions" />
|
||||
<orderEntry type="module" module-name="annotations" />
|
||||
|
||||
+2
-6
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.plugins.groovy.lang.psi.impl;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementEvaluator;
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
@@ -35,14 +35,10 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrRenameableLightEle
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class GroovyTargetElementEvaluator implements TargetElementEvaluator {
|
||||
public class GroovyTargetElementEvaluator extends TargetElementUtil {
|
||||
|
||||
public static final Key<Object> NAVIGATION_ELEMENT_IS_NOT_TARGET = Key.create("GroovyTargetElementEvaluator.DONT_FOLLOW_NAVIGATION_ELEMENT");
|
||||
|
||||
@Override
|
||||
public boolean includeSelfInGotoImplementation(@NotNull PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getElementByReference(@NotNull PsiReference ref, int flags) {
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.idea.maven.dom.references;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -34,7 +33,7 @@ public class MavenTargetUtil {
|
||||
public static PsiElement getFindTarget(Editor editor, PsiFile file) {
|
||||
if (editor == null || file == null) return null;
|
||||
|
||||
PsiElement target = TargetElementUtil.findTargetElement(editor, TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
|
||||
PsiElement target = TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
|
||||
if (target instanceof MavenPsiElementWrapper) {
|
||||
return ((MavenPsiElementWrapper)target).getWrappee();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package org.jetbrains.idea.maven.dom;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.codeInsight.documentation.DocumentationManager;
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
|
||||
@@ -353,7 +352,7 @@ public abstract class MavenDomTestCase extends MavenImportingTestCase {
|
||||
MapDataContext context = new MapDataContext();
|
||||
context.put(CommonDataKeys.EDITOR, getEditor(f));
|
||||
context.put(CommonDataKeys.PSI_FILE, getTestPsiFile(f));
|
||||
context.put(CommonDataKeys.PSI_ELEMENT, TargetElementUtil.findTargetElement(getEditor(f),
|
||||
context.put(CommonDataKeys.PSI_ELEMENT, TargetElementUtilBase.findTargetElement(getEditor(f),
|
||||
TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED
|
||||
| TargetElementUtilBase.ELEMENT_NAME_ACCEPTED));
|
||||
return context;
|
||||
|
||||
@@ -1363,8 +1363,12 @@
|
||||
|
||||
<indexPatternBuilder implementation="com.intellij.psi.impl.search.JavaIndexPatternBuilder"/>
|
||||
<indexPatternBuilder implementation="com.intellij.psi.impl.search.JspIndexPatternBuilder"/>
|
||||
|
||||
<applicationService serviceInterface="com.intellij.codeInsight.TargetElementUtilBase"
|
||||
serviceImplementation="com.intellij.codeInsight.TargetElementUtil"/>
|
||||
serviceImplementation="com.intellij.codeInsight.TargetElementUtilBase"/>
|
||||
<targetElementUtilExtender implementation="com.intellij.codeInsight.TargetElementUtil"/>
|
||||
<targetElementEvaluator language="JAVA" implementationClass="com.intellij.codeInsight.TargetElementUtil"/>
|
||||
|
||||
<gotoClassContributor implementation="com.intellij.ide.util.gotoByName.DefaultClassNavigationContributor"/>
|
||||
<gotoSymbolContributor implementation="com.intellij.ide.util.gotoByName.DefaultSymbolNavigationContributor"/>
|
||||
<scopeTreeExpander implementation="com.intellij.ide.scopeView.ClassesScopeTreeStructureExpander"/>
|
||||
|
||||
Reference in New Issue
Block a user