From 86a86d3c72c1b13cab7a616b9868d4cb9b71bf64 Mon Sep 17 00:00:00 2001 From: Roland Grunberg Date: Tue, 19 Jul 2022 22:06:07 -0400 Subject: [PATCH] Always interpret the full workspace symbol query as a package name. - For a query of 'foo.bar.baz', in addition to searching for all types matching 'baz', whose package matches 'foo.bar', we should also search for all types whose package matches 'foo.bar.baz' - Refactor custom TypeNameMatchRequestor & MethodNameMatchRequestor - Add testcase Signed-off-by: Roland Grunberg --- .../handlers/WorkspaceSymbolHandler.java | 241 ++++++++++-------- .../handlers/WorkspaceSymbolHandlerTest.java | 11 + 2 files changed, 150 insertions(+), 102 deletions(-) diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java index 5c13c9a56c..ce5d6fa841 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandler.java @@ -82,111 +82,21 @@ public static List search(String query, int maxResults, Strin PreferenceManager preferenceManager = JavaLanguageServerPlugin.getPreferencesManager(); - new SearchEngine().searchAllTypeNames(qualifierName == null ? null : qualifierName.toCharArray(), qualifierMatchRule, typeName.toCharArray(), typeMatchRule, IJavaSearchConstants.TYPE, searchScope, new TypeNameMatchRequestor() { - - @Override - public void acceptTypeNameMatch(TypeNameMatch match) { - try { - if (maxResults > 0 && symbols.size() >= maxResults) { - return; - } - Location location = null; - try { - if (!sourceOnly && match.getType().isBinary()) { - location = JDTUtils.toLocation(match.getType().getClassFile()); - } else if (!match.getType().isBinary()) { - location = JDTUtils.toLocation(match.getType()); - } - } catch (Exception e) { - JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getSimpleTypeName(), e); - return; - } - - if (location != null && match.getSimpleTypeName() != null && !match.getSimpleTypeName().isEmpty()) { - SymbolInformation symbolInformation = new SymbolInformation(); - symbolInformation.setContainerName(match.getTypeContainerName()); - symbolInformation.setName(match.getSimpleTypeName()); - symbolInformation.setKind(mapKind(match)); - if (Flags.isDeprecated(match.getType().getFlags())) { - if (preferenceManager != null && preferenceManager.getClientPreferences().isSymbolTagSupported()) { - symbolInformation.setTags(List.of(SymbolTag.Deprecated)); - } - else { - symbolInformation.setDeprecated(true); - } - } - symbolInformation.setLocation(location); - symbols.add(symbolInformation); - if (maxResults > 0 && symbols.size() >= maxResults) { - monitor.setCanceled(true); - } - } - } catch (Exception e) { - JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getSimpleTypeName(), e); - return; - } - } - - private SymbolKind mapKind(TypeNameMatch match) { - int flags = match.getModifiers(); - if (Flags.isInterface(flags)) { - return SymbolKind.Interface; - } - if (Flags.isAnnotation(flags)) { - return SymbolKind.Property; - } - if (Flags.isEnum(flags)) { - return SymbolKind.Enum; - } - return SymbolKind.Class; - } - }, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); + SearchEngine engine = new SearchEngine(); + boolean isSymbolTagSupported = preferenceManager != null && preferenceManager.getClientPreferences().isSymbolTagSupported(); + WorkspaceSymbolTypeRequestor typeRequestor = new WorkspaceSymbolTypeRequestor(symbols, maxResults, sourceOnly, isSymbolTagSupported, monitor); + if (!typeName.isEmpty()) { + // search for qualifier = qualifierName, type = typeName + engine.searchAllTypeNames(qualifierName == null ? null : qualifierName.toCharArray(), qualifierMatchRule, typeName.toCharArray(), typeMatchRule, IJavaSearchConstants.TYPE, searchScope,typeRequestor , IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); + } + // search for qualifier = qualiferName.typeName, type = null + engine.searchAllTypeNames(tQuery.toCharArray(), qualifierMatchRule, null, typeMatchRule, IJavaSearchConstants.TYPE, searchScope, typeRequestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); if (preferenceManager != null && preferenceManager.getPreferences().isIncludeSourceMethodDeclarations()) { monitor.beginTask("Searching methods...", 100); IJavaSearchScope nonSourceSearchScope = createSearchScope(projectName, true); - new SearchEngine().searchAllMethodNames(null, SearchPattern.R_PATTERN_MATCH, query.trim().toCharArray(), typeMatchRule, nonSourceSearchScope, new MethodNameMatchRequestor() { - - @Override - public void acceptMethodNameMatch(MethodNameMatch match) { - try { - if (maxResults > 0 && symbols.size() >= maxResults) { - return; - } - - Location location = null; - try { - location = JDTUtils.toLocation(match.getMethod()); - } catch (Exception e) { - JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getMethod().getElementName(), e); - return; - } - - if (location != null && match.getMethod().getElementName() != null && !match.getMethod().getElementName().isEmpty()) { - SymbolInformation symbolInformation = new SymbolInformation(); - symbolInformation.setContainerName(match.getMethod().getDeclaringType().getFullyQualifiedName()); - symbolInformation.setName(match.getMethod().getElementName()); - symbolInformation.setKind(SymbolKind.Method); - if (Flags.isDeprecated(match.getMethod().getFlags())) { - if (preferenceManager != null && preferenceManager.getClientPreferences().isSymbolTagSupported()) { - symbolInformation.setTags(List.of(SymbolTag.Deprecated)); - } - else { - symbolInformation.setDeprecated(true); - } - } - symbolInformation.setLocation(location); - symbols.add(symbolInformation); - if (maxResults > 0 && symbols.size() >= maxResults) { - monitor.setCanceled(true); - } - } - } catch (Exception e) { - JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getMethod().getElementName(), e); - return; - } - } - }, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); + WorkspaceSymbolMethodRequestor methodRequestor = new WorkspaceSymbolMethodRequestor(symbols, maxResults, isSymbolTagSupported, monitor); + engine.searchAllMethodNames(null, SearchPattern.R_PATTERN_MATCH, query.trim().toCharArray(), typeMatchRule, nonSourceSearchScope, methodRequestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor); } } catch (Exception e) { if (e instanceof OperationCanceledException) { @@ -229,4 +139,131 @@ public SearchSymbolParams(String query, String projectName) { this.projectName = projectName; } } -} \ No newline at end of file + + private static class WorkspaceSymbolTypeRequestor extends TypeNameMatchRequestor { + private ArrayList symbols; + private int maxResults; + private boolean sourceOnly; + private boolean isSymbolTagSupported; + private IProgressMonitor monitor; + + public WorkspaceSymbolTypeRequestor(ArrayList symbols, int maxResults, boolean sourceOnly, boolean isSymbolTagSupported, IProgressMonitor monitor) { + this.symbols = symbols; + this.maxResults = maxResults; + this.sourceOnly = sourceOnly; + this.isSymbolTagSupported = isSymbolTagSupported; + this.monitor = monitor; + } + + @Override + public void acceptTypeNameMatch(TypeNameMatch match) { + try { + if (maxResults > 0 && symbols.size() >= maxResults) { + monitor.setCanceled(true); + return; + } + Location location = null; + try { + if (!sourceOnly && match.getType().isBinary()) { + location = JDTUtils.toLocation(match.getType().getClassFile()); + } else if (!match.getType().isBinary()) { + location = JDTUtils.toLocation(match.getType()); + } + } catch (Exception e) { + JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getSimpleTypeName(), e); + return; + } + + if (location != null && match.getSimpleTypeName() != null && !match.getSimpleTypeName().isEmpty()) { + SymbolInformation symbolInformation = new SymbolInformation(); + symbolInformation.setContainerName(match.getTypeContainerName()); + symbolInformation.setName(match.getSimpleTypeName()); + symbolInformation.setKind(mapKind(match)); + if (Flags.isDeprecated(match.getType().getFlags())) { + if (isSymbolTagSupported) { + symbolInformation.setTags(List.of(SymbolTag.Deprecated)); + } else { + symbolInformation.setDeprecated(true); + } + } + symbolInformation.setLocation(location); + symbols.add(symbolInformation); + if (maxResults > 0 && symbols.size() >= maxResults) { + monitor.setCanceled(true); + } + } + } catch (Exception e) { + JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getSimpleTypeName(), e); + return; + } + } + + private SymbolKind mapKind(TypeNameMatch match) { + int flags = match.getModifiers(); + if (Flags.isInterface(flags)) { + return SymbolKind.Interface; + } + if (Flags.isAnnotation(flags)) { + return SymbolKind.Property; + } + if (Flags.isEnum(flags)) { + return SymbolKind.Enum; + } + return SymbolKind.Class; + } + } + + private static class WorkspaceSymbolMethodRequestor extends MethodNameMatchRequestor { + private ArrayList symbols; + private int maxResults; + private boolean isSymbolTagSupported; + private IProgressMonitor monitor; + + public WorkspaceSymbolMethodRequestor(ArrayList symbols, int maxResults, boolean isSymbolTagSupported, IProgressMonitor monitor) { + this.symbols = symbols; + this.maxResults = maxResults; + this.isSymbolTagSupported = isSymbolTagSupported; + this.monitor = monitor; + } + + @Override + public void acceptMethodNameMatch(MethodNameMatch match) { + try { + if (maxResults > 0 && symbols.size() >= maxResults) { + monitor.setCanceled(true); + return; + } + + Location location = null; + try { + location = JDTUtils.toLocation(match.getMethod()); + } catch (Exception e) { + JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getMethod().getElementName(), e); + return; + } + + if (location != null && match.getMethod().getElementName() != null && !match.getMethod().getElementName().isEmpty()) { + SymbolInformation symbolInformation = new SymbolInformation(); + symbolInformation.setContainerName(match.getMethod().getDeclaringType().getFullyQualifiedName()); + symbolInformation.setName(match.getMethod().getElementName()); + symbolInformation.setKind(SymbolKind.Method); + if (Flags.isDeprecated(match.getMethod().getFlags())) { + if (isSymbolTagSupported) { + symbolInformation.setTags(List.of(SymbolTag.Deprecated)); + } else { + symbolInformation.setDeprecated(true); + } + } + symbolInformation.setLocation(location); + symbols.add(symbolInformation); + if (maxResults > 0 && symbols.size() >= maxResults) { + monitor.setCanceled(true); + } + } + } catch (Exception e) { + JavaLanguageServerPlugin.logException("Unable to determine location for " + match.getMethod().getElementName(), e); + return; + } + } + } +} diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandlerTest.java index 0ce8daef64..1c0e796020 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandlerTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceSymbolHandlerTest.java @@ -187,6 +187,17 @@ public void testSearchQualifiedTypeWithWildcards() { assertTrue(results.stream().allMatch(s -> s.getName().endsWith("Exception") && s.getContainerName().contains(".lang"))); } + @Test + public void testSearchAllTypesOfPackage() { + List results = WorkspaceSymbolHandler.search("java.io", monitor); + assertTrue(results.size() > 1); + assertTrue(results.stream().anyMatch(s -> "File".equals(s.getName()) && "java.io".equals(s.getContainerName()))); + + results = WorkspaceSymbolHandler.search("java.lang", monitor); + assertTrue(results.size() > 1); + assertTrue(results.stream().anyMatch(s -> "Exception".equals(s.getName()) && "java.lang".equals(s.getContainerName()))); + } + @Test public void testSearchSourceMethodDeclarations() { preferences.setIncludeSourceMethodDeclarations(true);