From f9f6c29c3a583a4585cb8eddc71aaf7806b6cfa4 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 31 Jul 2012 20:50:58 +0200 Subject: [PATCH] go to line and member in go to class --- .../intellij/ide/actions/GotoClassAction.java | 83 +++++++++++++++++++ .../util/gotoByName/ChooseByNamePopup.java | 20 ++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java index 95e3b2d08bc5..3dc5d3385572 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java @@ -18,11 +18,19 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.navigation.NavigationUtil; import com.intellij.featureStatistics.FeatureUsageTracker; +import com.intellij.ide.structureView.StructureView; +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.util.EditSourceUtil; import com.intellij.ide.util.gotoByName.*; +import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.lang.Language; +import com.intellij.lang.LanguageStructureViewBuilder; +import com.intellij.lang.PsiStructureViewFactory; import com.intellij.navigation.AnonymousElementProvider; import com.intellij.navigation.ChooseByNameRegistry; +import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; @@ -30,12 +38,21 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.pom.Navigatable; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; +import com.intellij.psi.codeStyle.MinusculeMatcher; +import com.intellij.psi.codeStyle.NameUtil; +import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -68,6 +85,19 @@ public class GotoClassAction extends GotoActionBase implements DumbAware { try { if (element instanceof PsiElement) { final PsiElement psiElement = getElement(((PsiElement)element), popup); + final VirtualFile file = PsiUtilCore.getVirtualFile(psiElement); + if (popup.getLinePosition() != -1 && file != null) { + Navigatable n = new OpenFileDescriptor(project, file, popup.getLinePosition(), popup.getColumnPosition()).setUseCurrentWindow(popup.isOpenInCurrentWindowRequested()); + if (n.canNavigate()) { + n.navigate(true); + return; + } + } + if (psiElement != null && file != null && popup.getMemberPattern() != null) { + NavigationUtil.activateFileWithPsiElement(psiElement, !popup.isOpenInCurrentWindowRequested()); + findMember(popup.getMemberPattern(), psiElement, file); + } + NavigationUtil.activateFileWithPsiElement(psiElement, !popup.isOpenInCurrentWindowRequested()); } else { @@ -81,6 +111,59 @@ public class GotoClassAction extends GotoActionBase implements DumbAware { }, "Classes matching pattern", true); } + private static void findMember(String pattern, PsiElement psiElement, VirtualFile file) { + final PsiStructureViewFactory factory = LanguageStructureViewBuilder.INSTANCE.forLanguage(psiElement.getLanguage()); + final StructureViewBuilder builder = factory == null ? null : factory.getStructureViewBuilder(psiElement.getContainingFile()); + final FileEditor[] editors = FileEditorManager.getInstance(psiElement.getProject()).getEditors(file); + + if (builder != null && editors.length > 0) { + final StructureView view = builder.createStructureView(editors[0], psiElement.getProject()); + final StructureViewModel model = view.getTreeModel(); + final StructureViewTreeElement root = model.getRoot(); + final StructureViewTreeElement element = findElement(root, psiElement, 4); + if (element != null) { + final MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE); + int max = Integer.MIN_VALUE; + Object target = null; + for (TreeElement treeElement : element.getChildren()) { + if (treeElement instanceof StructureViewTreeElement) { + final ItemPresentation presentation = treeElement.getPresentation(); + if (presentation != null) { + final int degree = matcher.matchingDegree(presentation.getPresentableText()); + if (degree > max) { + max = degree; + target = ((StructureViewTreeElement)treeElement).getValue(); + } + } + } + } + + if (target instanceof Navigatable) { + ((Navigatable)target).navigate(true); + } + } + } + } + + @Nullable + private static StructureViewTreeElement findElement(StructureViewTreeElement node, PsiElement element, int hopes) { + final Object value = node.getValue(); + if (value instanceof PsiElement) { + if (((PsiElement)value).isEquivalentTo(element)) return node; + if (hopes != 0) { + for (TreeElement child : node.getChildren()) { + if (child instanceof StructureViewTreeElement) { + final StructureViewTreeElement e = findElement((StructureViewTreeElement)child, element, hopes - 1); + if (e != null) { + return e; + } + } + } + } + } + return null; + } + private static PsiElement getElement(PsiElement element, ChooseByNamePopup popup) { final String path = popup.getPathToAnonymous(); if (path != null) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java index 8cd469f0c0ab..ed7052f56ee9 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java @@ -294,19 +294,24 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP return newPopup; } - private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("(.+)(?::|@|,|#)(\\d+)?(?:(?:\\D)(\\d+)?)?"); + private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("(.+)(?::|@|,)(\\d+)?(?:(?:\\D)(\\d+)?)?"); private static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)"); + private static final Pattern patternToDetectMembers = Pattern.compile("(.+)(#)(.*)"); public String transformPattern(String pattern) { Pattern regex = null; if (pattern.indexOf(':') != -1 || pattern.indexOf(',') != -1 || pattern.indexOf(';') != -1 || - pattern.indexOf('#') != -1 || + //pattern.indexOf('#') != -1 || pattern.indexOf('@') != -1) { // quick test if reg exp should be used regex = patternToDetectLinesAndColumns; } + if (pattern.indexOf('#') != -1) { + regex = patternToDetectMembers; + } + if (pattern.indexOf('$') != -1) { regex = patternToDetectAnonymousClasses; } @@ -362,4 +367,15 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP public int getColumnPosition() { return getLineOrColumn(false); } + + @Nullable + public String getMemberPattern() { + final int index = getEnteredText().lastIndexOf('#'); + if (index == -1) { + return null; + } + + String name = getEnteredText().substring(index + 1).trim(); + return StringUtil.isEmpty(name) ? null : name; + } }