PY-18253: PyLineMarkerNavigator test added

This commit is contained in:
Ilya.Kazakevich
2016-01-29 20:09:24 +03:00
parent 9e77cfdff7
commit 68cd5b1668
7 changed files with 107 additions and 3 deletions
@@ -18,6 +18,9 @@ package com.jetbrains.python.codeInsight;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
import com.intellij.util.Processor;
@@ -25,6 +28,7 @@ import com.intellij.util.Query;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
@@ -33,11 +37,17 @@ import java.util.List;
/**
* @author yole
*/
public abstract class PyLineMarkerNavigator<T extends PsiElement> implements GutterIconNavigationHandler<T> {
abstract class PyLineMarkerNavigator<T extends PsiElement> implements GutterIconNavigationHandler<T> {
private static final Key<NavigatablePsiElement[]> MARKERS = new Key<NavigatablePsiElement[]>("PyLineMarkerNavigatorMarkers");
@Override
public void navigate(final MouseEvent e, final T elt) {
final List<NavigatablePsiElement> navElements = new ArrayList<NavigatablePsiElement>();
final Query<T> elementQuery = search(elt, TypeEvalContext.userInitiated(elt.getProject(), elt.getContainingFile()));
if (elementQuery == null) return;
if (elementQuery == null) {
return;
}
elementQuery.forEach(new Processor<T>() {
public boolean process(final T psiElement) {
if (psiElement instanceof NavigatablePsiElement) {
@@ -46,8 +56,27 @@ public abstract class PyLineMarkerNavigator<T extends PsiElement> implements Gut
return true;
}
});
/**
* For test purposes, we should be able to access list of methods to check em.
* {@link PsiElementListNavigator} simply opens then (hence it is swing-based) and can't be used in tests.
* So, in unit tests we save data in element and data could be obtained with {@link #getNavigationTargets(UserDataHolder)}
*/
final NavigatablePsiElement[] methods = navElements.toArray(new NavigatablePsiElement[navElements.size()]);
PsiElementListNavigator.openTargets(e, methods, getTitle(elt), null, new DefaultPsiElementCellRenderer());
if (ApplicationManager.getApplication().isUnitTestMode()) {
elt.putUserData(MARKERS, methods);
}
else {
PsiElementListNavigator.openTargets(e, methods, getTitle(elt), null, new DefaultPsiElementCellRenderer());
}
}
/**
* @see {@link #navigate(MouseEvent, PsiElement)} and {@link #MARKERS}
*/
@TestOnly
@Nullable
static NavigatablePsiElement[] getNavigationTargets(@NotNull final UserDataHolder holder) {
return holder.getUserData(MARKERS);
}
protected abstract String getTitle(T elt);
@@ -0,0 +1,3 @@
class Eggs(object):
def ham(self):
pass
+4
View File
@@ -0,0 +1,4 @@
import eggs.spam.eggs
class Child(eggs.spam.eggs.Eggs):
def h<caret>am(self):
pass
@@ -0,0 +1,68 @@
/*
* Copyright 2000-2016 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.jetbrains.python.codeInsight;
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.lang.ASTNode;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.TokenSet;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyPossibleClassMember;
import org.hamcrest.Matchers;
import org.junit.Assert;
import javax.swing.*;
import java.awt.event.MouseEvent;
/**
* @author Ilya.Kazakevich
*/
public final class PyLineMarkerProviderTest extends PyTestCase {
/**
* Checks method has "up" arrow when overrides, and this arrow works
*/
public void testOverriding() throws Exception {
myFixture.copyDirectoryToProject("lineMarkerTest", "");
myFixture.configureByFile("spam.py");
final ASTNode functionNode = myFixture.getElementAtCaret().getNode();
// We need IDENTIFIER node
final ASTNode[] functionChildren = functionNode.getChildren(TokenSet.create(PyTokenTypes.IDENTIFIER));
assert functionChildren.length == 1 : "Wrong number of identifiers: " + functionChildren.length;
final PsiElement element = functionChildren[0].getPsi();
@SuppressWarnings("unchecked")
final LineMarkerInfo<PsiElement> lineMarkerInfo = new PyLineMarkerProvider().getLineMarkerInfo(element);
Assert.assertNotNull("No gutter displayed", lineMarkerInfo);
final GutterIconNavigationHandler<PsiElement> handler = lineMarkerInfo.getNavigationHandler();
Assert.assertNotNull("Gutter has no navigation handle", handler);
handler.navigate(new MouseEvent(new JLabel(), 0, 0, 0, 0, 0, 0, false), element);
final NavigatablePsiElement[] targets = PyLineMarkerNavigator.getNavigationTargets(element);
Assert.assertNotNull("No navigation targets found", targets);
Assert.assertThat("Wrong number of targets found", targets, Matchers.arrayWithSize(1));
final NavigatablePsiElement parentMethod = targets[0];
Assert.assertThat("Navigation target has wrong type", parentMethod, Matchers.instanceOf(PyPossibleClassMember.class));
final PyClass parentClass = ((PyPossibleClassMember)parentMethod).getContainingClass();
Assert.assertNotNull("Function overrides other function, but no parent displayed", parentClass);
Assert.assertEquals("Wrong parent class name", "Eggs", parentClass.getName());
}
}