Honor node providers when building navbar from structure (IDEA-231342)
authorDmitry Jemerov <yole@jetbrains.com>
Tue, 28 Jan 2020 14:42:16 +0000 (15:42 +0100)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Tue, 28 Jan 2020 19:03:30 +0000 (19:03 +0000)
GitOrigin-RevId: 3e2322ff7ee747ed016423835682052acb966a67

java/java-impl/src/com/intellij/ide/navigationToolbar/JavaNavBarExtension.java
java/java-tests/testData/ide/navigationToolbar/lambdaExpression.java [new file with mode: 0644]
java/java-tests/testSrc/com/intellij/ide/navigationToolbar/JavaNavBarTest.java
platform/lang-impl/src/com/intellij/ide/navigationToolbar/StructureAwareNavBarModelExtension.kt

index 54531b5a7a316f2c257096a04c907639ad7fb9ad..e54e56a0c094edd0eabdb1375d9a218677be2faf 100644 (file)
@@ -1,8 +1,12 @@
 // Copyright 2000-2020 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.ide.navigationToolbar;
 
+import com.google.common.collect.ImmutableList;
 import com.intellij.analysis.AnalysisScopeBundle;
+import com.intellij.ide.structureView.impl.java.JavaAnonymousClassesNodeProvider;
+import com.intellij.ide.structureView.impl.java.JavaLambdaNodeProvider;
 import com.intellij.ide.ui.UISettings;
+import com.intellij.ide.util.treeView.smartTree.NodeProvider;
 import com.intellij.lang.LangBundle;
 import com.intellij.lang.Language;
 import com.intellij.lang.java.JavaLanguage;
@@ -17,12 +21,16 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
 
+import java.util.List;
+
 import static com.intellij.psi.util.PsiFormatUtilBase.*;
 
 /**
  * @author anna
  */
 public class JavaNavBarExtension extends StructureAwareNavBarModelExtension {
+  private final List<NodeProvider<?>> myNodeProviders = ImmutableList.of(new JavaLambdaNodeProvider(), new JavaAnonymousClassesNodeProvider());
+
   @Nullable
   @Override
   public String getPresentableText(Object object) {
@@ -47,6 +55,9 @@ public class JavaNavBarExtension extends StructureAwareNavBarModelExtension {
     else if (object instanceof PsiDirectory && JrtFileSystem.isRoot(((PsiDirectory)object).getVirtualFile())) {
       return LangBundle.message("jrt.node.short");
     }
+    else if (object instanceof PsiLambdaExpression) {
+      return "Lambda";
+    }
     return null;
   }
 
@@ -95,4 +106,10 @@ public class JavaNavBarExtension extends StructureAwareNavBarModelExtension {
   protected Language getLanguage() {
     return JavaLanguage.INSTANCE;
   }
+
+  @NotNull
+  @Override
+  protected List<NodeProvider<?>> getApplicableNodeProviders() {
+    return myNodeProviders;
+  }
 }
diff --git a/java/java-tests/testData/ide/navigationToolbar/lambdaExpression.java b/java/java-tests/testData/ide/navigationToolbar/lambdaExpression.java
new file mode 100644 (file)
index 0000000..b531015
--- /dev/null
@@ -0,0 +1,5 @@
+class LambdaExpression {
+  public void foo() {
+    new ArrayList<String>().forEach((x) -> System.out.<caret>println(x));
+  }
+}
\ No newline at end of file
index 2ebfe360908faa04d8b38d2608c1f112f2508b8e..9aeaf06d219066fd43df7dec45e6adb1f0fe4925 100644 (file)
@@ -27,6 +27,11 @@ public class JavaNavBarTest extends LightJavaCodeInsightFixtureTestCase {
     assertNavBarModel("src", "EnumMember", "BAR", "foo");
   }
 
+  public void testLambdaExpression() {
+    myFixture.configureByFile("lambdaExpression.java");
+    assertNavBarModel("src", "LambdaExpression", "foo", "Lambda");
+  }
+
   public void assertNavBarModel(String... expectedItems) {
     NavBarModel model = new NavBarModel(myFixture.getProject());
     model.updateModel(((EditorEx)myFixture.getEditor()).getDataContext());
@@ -34,6 +39,6 @@ public class JavaNavBarTest extends LightJavaCodeInsightFixtureTestCase {
     for (int i = 0; i < model.size(); i++) {
       items.add(NavBarPresentation.calcPresentableText(model.get(i), false));
     }
-    assertSameElements(items, expectedItems);
+    assertOrderedEquals(items, expectedItems);
   }
 }
index 00042c4dd3854a483622904f065ac00ca9ef7d31..541f43c3ed6913219a9bd3a494e15ae60fba86b0 100644 (file)
@@ -5,6 +5,8 @@ import com.intellij.ide.structureView.StructureViewModel
 import com.intellij.ide.structureView.StructureViewTreeElement
 import com.intellij.ide.structureView.TreeBasedStructureViewBuilder
 import com.intellij.ide.ui.UISettings
+import com.intellij.ide.util.treeView.smartTree.NodeProvider
+import com.intellij.ide.util.treeView.smartTree.TreeElement
 import com.intellij.lang.Language
 import com.intellij.lang.LanguageStructureViewBuilder
 import com.intellij.openapi.actionSystem.CommonDataKeys
@@ -67,7 +69,7 @@ abstract class StructureAwareNavBarModelExtension : AbstractNavBarModelExtension
   }
 
   private fun findParentInModel(root: StructureViewTreeElement, psiElement: PsiElement): PsiElement? {
-    for (child in root.children) {
+    for (child in childrenFromNodeAndProviders(root)) {
       if ((child as StructureViewTreeElement).value == psiElement) {
         return root.value as? PsiElement
       }
@@ -91,19 +93,25 @@ abstract class StructureAwareNavBarModelExtension : AbstractNavBarModelExtension
     return model
   }
 
-  private fun processStructureViewChildren(root: StructureViewTreeElement,
+  private fun processStructureViewChildren(parent: StructureViewTreeElement,
                                            `object`: Any,
                                            processor: Processor<Any>): Boolean {
-    if (root.value == `object`) {
-      return root.children
+    if (parent.value == `object`) {
+      return childrenFromNodeAndProviders(parent)
         .filterIsInstance<StructureViewTreeElement>()
         .all { processor.process(it.value) }
     }
 
-    return root.children
+    return childrenFromNodeAndProviders(parent)
       .filterIsInstance<StructureViewTreeElement>()
       .all { processStructureViewChildren(it, `object`, processor) }
   }
 
+  private fun childrenFromNodeAndProviders(parent: StructureViewTreeElement): List<TreeElement> {
+    return parent.children.toList() + applicableNodeProviders.flatMap { it.provideNodes(parent) }
+  }
+
   override fun normalizeChildren() = false
+
+  protected open val applicableNodeProviders: List<NodeProvider<*>> = emptyList()
 }
\ No newline at end of file