Navigate to symbol for kotlin properties

This commit is contained in:
Nikolay Krasko
2012-10-16 14:52:28 +04:00
parent bc85a8bf6b
commit 04670d5d6e
11 changed files with 227 additions and 7 deletions
@@ -17,6 +17,8 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
@@ -169,4 +171,9 @@ public class JetProperty extends JetTypeParameterListOwnerStub<PsiJetPropertyStu
assert node != null : "Val or var should always exist for property";
return node;
}
@Override
public ItemPresentation getPresentation() {
return ItemPresentationProviders.getItemPresentation(this);
}
}
+2
View File
@@ -184,6 +184,7 @@
<iconProvider implementation="org.jetbrains.jet.plugin.JetIconProvider"/>
<itemPresentationProvider implementationClass="org.jetbrains.jet.plugin.presentation.JetFunctionPresenter" forClass="org.jetbrains.jet.lang.psi.JetNamedFunction"/>
<itemPresentationProvider implementationClass="org.jetbrains.jet.plugin.presentation.JetClassPresenter" forClass="org.jetbrains.jet.lang.psi.JetClass"/>
<itemPresentationProvider implementationClass="org.jetbrains.jet.plugin.presentation.JetPropertyPresenter" forClass="org.jetbrains.jet.lang.psi.JetProperty"/>
<gotoTargetRendererProvider id="JetGotoTargetRenderProvider" implementation="org.jetbrains.jet.plugin.JetGotoTargetRenderProvider" order="first"/>
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
<findUsagesHandlerFactory implementation="org.jetbrains.jet.plugin.findUsages.KotlinFindUsagesHandlerFactory"/>
@@ -198,6 +199,7 @@
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetShortClassNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetShortFunctionNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetShortPropertiesNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetAllShortFunctionNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetSuperClassIndex"/>
@@ -38,19 +38,26 @@ public class JetGotoSymbolContributor implements ChooseByNameContributor {
@NotNull
@Override
public String[] getNames(Project project, boolean includeNonProjectItems) {
final Collection<String> items = StubIndex.getInstance().getAllKeys(JetIndexKeys.FUNCTIONS_SHORT_NAME_KEY, project);
Collection<String> items = StubIndex.getInstance().getAllKeys(JetIndexKeys.FUNCTIONS_SHORT_NAME_KEY, project);
items.addAll(StubIndex.getInstance().getAllKeys(JetIndexKeys.PROPERTIES_SHORT_NAME_KEY, project));
return ArrayUtil.toStringArray(items);
}
@NotNull
@Override
public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) {
final GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
final Collection<? extends NavigationItem> functions = StubIndex.getInstance().get(
Collection<? extends NavigationItem> functions = StubIndex.getInstance().get(
JetIndexKeys.FUNCTIONS_SHORT_NAME_KEY, name, project, scope);
Collection<? extends NavigationItem> properties = StubIndex.getInstance().get(
JetIndexKeys.PROPERTIES_SHORT_NAME_KEY, name, project, scope);
final List<NavigationItem> items = new ArrayList<NavigationItem>(Collections2.filter(functions, Predicates.notNull()));
items.addAll(properties);
return ArrayUtil.toObjectArray(items, NavigationItem.class);
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.presentation;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProvider;
import org.jetbrains.jet.lang.psi.JetProperty;
public class JetPropertyPresenter implements ItemPresentationProvider<JetProperty> {
@Override
public ItemPresentation getPresentation(final JetProperty item) {
return new JetDefaultNamedDeclarationPresentation(item);
}
}
@@ -44,6 +44,7 @@ public interface JetIndexKeys {
StubIndexKey.createIndexKey("jet.top.level.property.fqn.name");
StubIndexKey<String, JetNamedFunction> FUNCTIONS_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.functions.short.name");
StubIndexKey<String, JetProperty> PROPERTIES_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.properties.short.name");
StubIndexKey<String, JetAnnotationEntry> ANNOTATIONS_KEY = StubIndexKey.createIndexKey("jet.annotations");
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.stubindex;
import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetProperty;
import java.util.Collection;
public class JetShortPropertiesNameIndex extends StringStubIndexExtension<JetProperty> {
private static final JetShortPropertiesNameIndex ourInstance = new JetShortPropertiesNameIndex();
public static JetShortPropertiesNameIndex getInstance() {
return ourInstance;
}
@NotNull
@Override
public StubIndexKey<String, JetProperty> getKey() {
return JetIndexKeys.PROPERTIES_SHORT_NAME_KEY;
}
@Override
public Collection<JetProperty> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
return super.get(s, project, new JetSourceFilterScope(scope));
}
}
@@ -81,11 +81,16 @@ public class StubIndexServiceImpl implements StubIndexService {
@Override
public void indexProperty(PsiJetPropertyStub stub, IndexSink sink) {
if (stub.isTopLevel()) {
FqName topFQName = stub.getTopFQName();
if (topFQName != null) {
sink.occurrence(JetIndexKeys.TOP_LEVEL_PROPERTY_FQN_NAME_KEY, topFQName.toString());
String propertyName = stub.getName();
if (propertyName != null) {
if (stub.isTopLevel()) {
FqName topFQName = stub.getTopFQName();
if (topFQName != null) {
sink.occurrence(JetIndexKeys.TOP_LEVEL_PROPERTY_FQN_NAME_KEY, topFQName.toString());
}
}
sink.occurrence(JetIndexKeys.PROPERTIES_SHORT_NAME_KEY, propertyName);
}
}
@@ -0,0 +1,12 @@
fun testFunction() {
}
class Some {
fun testFunInClass() = 12
}
// SEARCH_TEXT: test
// REF: (in <root>).testFunction()
// REF: (in Some).testFunInClass()
@@ -0,0 +1,23 @@
val testGlobal = 12
fun some() {
val testInFun = 12
}
trait SomeTrait {
val testInTrait
}
class Some() {
val testInClass = 12
class object {
val testInClassObject = 12
}
}
// SEARCH_TEXT: test
// REF: (<root>).testGlobal
// REF: (Some).testInClass
// REF: (Some).testInClassObject
// REF: (SomeTrait).testInTrait
@@ -21,15 +21,20 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.intellij.codeInsight.navigation.GotoImplementationHandler;
import com.intellij.codeInsight.navigation.GotoTargetHandler;
import com.intellij.ide.util.gotoByName.GotoSymbolModel2;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.UsefulTestCase;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.InTextDirectivesUtils;
import org.jetbrains.jet.testing.ReferenceUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -67,4 +72,36 @@ public final class ImplementationTestUtils {
UsefulTestCase.assertEmpty(expectedReferences);
}
}
public static void assertGotoSymbol(@NotNull Project project, @NotNull Editor editor) {
List<String> searchTextList = InTextDirectivesUtils.findListWithPrefix("// SEARCH_TEXT:", editor.getDocument().getText());
Assert.assertFalse("There's no search text in test data file given. Use '// SEARCH_TEXT:' directive",
searchTextList.isEmpty());
List<String> expectedReferences = InTextDirectivesUtils.findListWithPrefix("// REF:", editor.getDocument().getText());
String searchText = searchTextList.get(0);
List<Object> elementsByName = new ArrayList<Object>();
GotoSymbolModel2 model = new GotoSymbolModel2(project);
String[] names = model.getNames(false);
for (String name : names) {
if (name != null && name.startsWith(searchText)) {
elementsByName.addAll(Arrays.asList(model.getElementsByName(name, false, name + "*", new ProgressIndicatorBase())));
}
}
List<String> renderedElements = Lists.transform(elementsByName, new Function<Object, String>() {
@Override
public String apply(@Nullable Object element) {
Assert.assertNotNull(element);
Assert.assertTrue(element instanceof PsiElement);
return ReferenceUtils.renderAsGotoImplementation((PsiElement) element);
}
});
UsefulTestCase.assertOrderedEquals(Ordering.natural().sortedCopy(renderedElements), expectedReferences);
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2012 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 org.jetbrains.jet.plugin.navigation;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.JetLightProjectDescriptor;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.File;
public class JetGotoSymbolTest extends LightCodeInsightFixtureTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JetLightProjectDescriptor.INSTANCE;
}
public void testProperties() {
doTest();
}
public void testFunctions() {
doTest();
}
@Override
protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/navigation/gotoSymbol").getPath() + File.separator;
}
protected void doTest() {
String fileName = getTestName(true) + ".kt";
myFixture.configureByFile(fileName);
ImplementationTestUtils.assertGotoSymbol(getProject(), myFixture.getEditor());
}
}