From 985b43adbe80851570c1bb12f3aa4c4e9f93ae64 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Sun, 17 Sep 2017 17:44:52 +0200 Subject: [PATCH] added symbol per document handling to annotation indexer mechanism --- .../boot/java/BootJavaLanguageServer.java | 28 ++-- .../boot/java/beans/BeansSymbolProvider.java | 28 ++++ .../java/beans/ComponentSymbolProvider.java | 28 ++++ .../ide/vscode/boot/java/beans/Constants.java | 21 +++ .../BootJavaDocumentSymbolHandler.java | 145 +----------------- .../BootJavaWorkspaceSymbolHandler.java | 6 +- .../boot/java/utils/AnnotationIndexer.java | 12 +- .../utils/test/AnnotationIndexerTest.java | 25 +++ 8 files changed, 134 insertions(+), 159 deletions(-) create mode 100644 headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java create mode 100644 headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java create mode 100644 headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/Constants.java diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java index 22827ed54..434620d08 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServer.java @@ -13,6 +13,8 @@ package org.springframework.ide.vscode.boot.java; import java.util.HashMap; import java.util.Map; +import org.springframework.ide.vscode.boot.java.beans.BeansSymbolProvider; +import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider; import org.springframework.ide.vscode.boot.java.handlers.BootJavaCodeLensEngine; import org.springframework.ide.vscode.boot.java.handlers.BootJavaCompletionEngine; import org.springframework.ide.vscode.boot.java.handlers.BootJavaDocumentSymbolHandler; @@ -27,6 +29,7 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingHoverProvider; import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider; import org.springframework.ide.vscode.boot.java.scope.ScopeCompletionProcessor; +import org.springframework.ide.vscode.boot.java.utils.AnnotationIndexer; import org.springframework.ide.vscode.boot.java.value.ValueCompletionProcessor; import org.springframework.ide.vscode.boot.java.value.ValueHoverProvider; import org.springframework.ide.vscode.boot.java.value.ValuePropertyReferencesProvider; @@ -39,13 +42,11 @@ import org.springframework.ide.vscode.commons.languageserver.java.DefaultJavaPro import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy; import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine; -import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler; import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler; import org.springframework.ide.vscode.commons.languageserver.util.ReferencesHandler; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService; -import org.springframework.ide.vscode.commons.languageserver.util.WorkspaceSymbolHandler; import org.springframework.ide.vscode.commons.maven.JavaProjectWithClasspathFileFinderStrategy; import org.springframework.ide.vscode.commons.maven.MavenCore; import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy; @@ -88,13 +89,15 @@ public class BootJavaLanguageServer extends SimpleLanguageServer { ReferencesHandler referencesHandler = createReferenceHandler(this, javaProjectFinder); documents.onReferences(referencesHandler); - documents.onDocumentSymbol(createDocumentSymbolHandler(this, javaProjectFinder)); + + AnnotationIndexer indexer = createAnnotationIndexer(this, javaProjectFinder); + documents.onDocumentSymbol(new BootJavaDocumentSymbolHandler(this, indexer)); + workspaceService.onWorkspaceSymbol(new BootJavaWorkspaceSymbolHandler(this, indexer)); BootJavaCodeLensEngine codeLensHandler = createCodeLensEngine(this, javaProjectFinder); documents.onCodeLens(codeLensHandler::createCodeLenses); documents.onCodeLensResolve(codeLensHandler::resolveCodeLens); - workspaceService.onWorkspaceSymbol(createWorkspaceSymbolHandler(this, javaProjectFinder)); } public void setMaxCompletionsNumber(int number) { @@ -122,7 +125,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer { return new BootJavaHoverProvider(this, javaProjectFinder, providers); } - protected DocumentSymbolHandler createDocumentSymbolHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder) { + protected AnnotationIndexer createAnnotationIndexer(SimpleLanguageServer server, JavaProjectFinder projectFinder) { HashMap providers = new HashMap<>(); providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider()); providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_GET_MAPPING, new RequestMappingSymbolProvider()); @@ -131,19 +134,10 @@ public class BootJavaLanguageServer extends SimpleLanguageServer { providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_DELETE_MAPPING, new RequestMappingSymbolProvider()); providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_PATCH_MAPPING, new RequestMappingSymbolProvider()); - return new BootJavaDocumentSymbolHandler(server, projectFinder, providers); - } + providers.put(org.springframework.ide.vscode.boot.java.beans.Constants.SPRING_BEAN, new BeansSymbolProvider()); + providers.put(org.springframework.ide.vscode.boot.java.beans.Constants.SPRING_COMPONENT, new ComponentSymbolProvider()); - protected WorkspaceSymbolHandler createWorkspaceSymbolHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder) { - HashMap providers = new HashMap<>(); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider()); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_GET_MAPPING, new RequestMappingSymbolProvider()); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_POST_MAPPING, new RequestMappingSymbolProvider()); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_PUT_MAPPING, new RequestMappingSymbolProvider()); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_DELETE_MAPPING, new RequestMappingSymbolProvider()); - providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_PATCH_MAPPING, new RequestMappingSymbolProvider()); - - return new BootJavaWorkspaceSymbolHandler(server, projectFinder, providers); + return new AnnotationIndexer(projectFinder, providers); } protected ReferencesHandler createReferenceHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder) { diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java new file mode 100644 index 000000000..47e2d005f --- /dev/null +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2017 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.beans; + +import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.lsp4j.SymbolInformation; +import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; +import org.springframework.ide.vscode.commons.util.text.TextDocument; + +/** + * @author Martin Lippert + */ +public class BeansSymbolProvider implements SymbolProvider { + + @Override + public SymbolInformation getSymbol(Annotation node, TextDocument doc) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java new file mode 100644 index 000000000..021fa5cf2 --- /dev/null +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2017 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.beans; + +import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.lsp4j.SymbolInformation; +import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider; +import org.springframework.ide.vscode.commons.util.text.TextDocument; + +/** + * @author Martin Lippert + */ +public class ComponentSymbolProvider implements SymbolProvider { + + @Override + public SymbolInformation getSymbol(Annotation node, TextDocument doc) { + return null; + } + +} diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/Constants.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/Constants.java new file mode 100644 index 000000000..0175f21c9 --- /dev/null +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/Constants.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2017 Pivotal, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Pivotal, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.vscode.boot.java.beans; + +/** + * @author Martin Lippert + */ +public class Constants { + + public static final String SPRING_COMPONENT = "org.springframework.stereotype.Component"; + public static final String SPRING_BEAN = "org.springframework.context.annotation.Bean"; + +} diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaDocumentSymbolHandler.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaDocumentSymbolHandler.java index ace21bb42..ce0cd5b8b 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaDocumentSymbolHandler.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaDocumentSymbolHandler.java @@ -11,34 +11,13 @@ package org.springframework.ide.vscode.boot.java.handlers; import java.nio.file.Path; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTParser; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.Annotation; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.MarkerAnnotation; -import org.eclipse.jdt.core.dom.NormalAnnotation; -import org.eclipse.jdt.core.dom.SingleMemberAnnotation; import org.eclipse.lsp4j.DocumentSymbolParams; -import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; -import org.eclipse.lsp4j.SymbolKind; -import org.springframework.ide.vscode.commons.java.IClasspath; -import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; +import org.springframework.ide.vscode.boot.java.utils.AnnotationIndexer; import org.springframework.ide.vscode.commons.languageserver.util.DocumentSymbolHandler; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; -import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService; -import org.springframework.ide.vscode.commons.util.text.IDocument; -import org.springframework.ide.vscode.commons.util.text.TextDocument; /** * @author Martin Lippert @@ -46,129 +25,21 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; public class BootJavaDocumentSymbolHandler implements DocumentSymbolHandler { private SimpleLanguageServer server; - private JavaProjectFinder projectFinder; - private Map symbolProviders; + private AnnotationIndexer indexer; - public BootJavaDocumentSymbolHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder, Map specificProviders) { + public BootJavaDocumentSymbolHandler(SimpleLanguageServer server, AnnotationIndexer indexer) { this.server = server; - this.projectFinder = projectFinder; - this.symbolProviders = specificProviders; + this.indexer = indexer; } @Override public List handle(DocumentSymbolParams params) { - SimpleTextDocumentService documents = server.getTextDocumentService(); - TextDocument doc = documents.get(params.getTextDocument().getUri()).copy(); - if (doc != null) { - try { - return provideDocumentSymbols(doc); - } catch (Exception e) { - e.printStackTrace(); - } - } + Path root = this.server.getWorkspaceRoot(); - return SimpleTextDocumentService.NO_SYMBOLS; - } + indexer.reset(); + indexer.scanFiles(root.toFile()); - private List provideDocumentSymbols(TextDocument document) throws Exception { - ASTParser parser = ASTParser.newParser(AST.JLS8); - Map options = JavaCore.getOptions(); - JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options); - parser.setCompilerOptions(options); - parser.setKind(ASTParser.K_COMPILATION_UNIT); - parser.setStatementsRecovery(true); - parser.setBindingsRecovery(true); - parser.setResolveBindings(true); - - String[] classpathEntries = getClasspathEntries(document); - String[] sourceEntries = new String[] {}; - parser.setEnvironment(classpathEntries, sourceEntries, null, true); - - String docURI = document.getUri(); - String unitName = docURI.substring(docURI.lastIndexOf("/")); - parser.setUnitName(unitName); - parser.setSource(document.get(0, document.getLength()).toCharArray()); - - CompilationUnit cu = (CompilationUnit) parser.createAST(null); - if (cu != null) { - System.out.println("AST node found: " + cu.getClass().getName()); - return provideDocumentSymbolsForAnnotations(cu, document); - } - - return null; - } - - private List provideDocumentSymbolsForAnnotations(ASTNode node, TextDocument doc) { - List result = new ArrayList<>(); - ASTVisitor visitor = new ASTVisitor() { - - @Override - public boolean visit(SingleMemberAnnotation node) { - extractSymbol(node, doc, result); - return super.visit(node); - } - - @Override - public boolean visit(NormalAnnotation node) { - extractSymbol(node, doc, result); - return super.visit(node); - } - - @Override - public boolean visit(MarkerAnnotation node) { - extractSymbol(node, doc, result); - return super.visit(node); - } - }; - node.accept(visitor); - - return result; - } - - private void extractSymbol(Annotation node, TextDocument doc, List result) { - System.out.println("annotation found: " + node.toString()); - ITypeBinding typeBinding = node.resolveTypeBinding(); - - if (typeBinding != null) { - String qualifiedTypeName = typeBinding.getQualifiedName(); - - SymbolProvider provider = symbolProviders.get(qualifiedTypeName); - if (provider != null) { - SymbolInformation symbol = provider.getSymbol(node, doc); - if (symbol != null) { - result.add(symbol); - } - } - else { - provideDefaultSymbol(node, doc, result); - } - } - } - - private void provideDefaultSymbol(Annotation node, TextDocument doc, List result) { - try { - ITypeBinding type = node.resolveTypeBinding(); - if (type != null) { - String qualifiedName = type.getQualifiedName(); - if (qualifiedName != null && qualifiedName.startsWith("org.springframework")) { - SymbolInformation symbol = new SymbolInformation(node.toString(), SymbolKind.Interface, - new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()))); - result.add(symbol); - } - } - } - catch (Exception e) { - e.printStackTrace(); - } - } - - private String[] getClasspathEntries(IDocument doc) throws Exception { - IJavaProject project = this.projectFinder.find(doc); - IClasspath classpath = project.getClasspath(); - Stream classpathEntries = classpath.getClasspathEntries(); - return classpathEntries - .filter(path -> path.toFile().exists()) - .map(path -> path.toAbsolutePath().toString()).toArray(String[]::new); + return indexer.getSymbols(params.getTextDocument().getUri()); } } diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaWorkspaceSymbolHandler.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaWorkspaceSymbolHandler.java index 9bec1ad08..0845d49fa 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaWorkspaceSymbolHandler.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/handlers/BootJavaWorkspaceSymbolHandler.java @@ -12,12 +12,10 @@ package org.springframework.ide.vscode.boot.java.handlers; import java.nio.file.Path; import java.util.List; -import java.util.Map; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.WorkspaceSymbolParams; import org.springframework.ide.vscode.boot.java.utils.AnnotationIndexer; -import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder; import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer; import org.springframework.ide.vscode.commons.languageserver.util.WorkspaceSymbolHandler; @@ -29,9 +27,9 @@ public class BootJavaWorkspaceSymbolHandler implements WorkspaceSymbolHandler { private SimpleLanguageServer server; private AnnotationIndexer indexer; - public BootJavaWorkspaceSymbolHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder, Map specificProviders) { + public BootJavaWorkspaceSymbolHandler(SimpleLanguageServer server, AnnotationIndexer indexer) { this.server = server; - this.indexer = new AnnotationIndexer(projectFinder, specificProviders); + this.indexer = indexer; } @Override diff --git a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/AnnotationIndexer.java b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/AnnotationIndexer.java index 7312b79cd..863e1fec8 100644 --- a/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/AnnotationIndexer.java +++ b/headless-services/boot-java-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/AnnotationIndexer.java @@ -18,6 +18,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -51,12 +53,14 @@ public class AnnotationIndexer { private Map symbolProviders; private List symbols; + private ConcurrentMap> symbolsByDoc; public AnnotationIndexer(JavaProjectFinder projectFinder, Map specificProviders) { this.projectFinder = projectFinder; this.symbolProviders = specificProviders; this.symbols = new ArrayList<>(); + this.symbolsByDoc = new ConcurrentHashMap<>(); } public void reset() { @@ -64,7 +68,11 @@ public class AnnotationIndexer { } public List getAllSymbols() { - return symbols; + return this.symbols; + } + + public List getSymbols(String docURI) { + return this.symbolsByDoc.get(docURI); } public void scanFiles(File directory) { @@ -172,12 +180,14 @@ public class AnnotationIndexer { SymbolInformation symbol = provider.getSymbol(node, doc); if (symbol != null) { symbols.add(symbol); + symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList()).add(symbol); } } else { SymbolInformation symbol = provideDefaultSymbol(node, doc); if (symbol != null) { symbols.add(symbol); + symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList()).add(symbol); } } } diff --git a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/AnnotationIndexerTest.java b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/AnnotationIndexerTest.java index da6b784ea..884428ad5 100644 --- a/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/AnnotationIndexerTest.java +++ b/headless-services/boot-java-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/AnnotationIndexerTest.java @@ -71,6 +71,31 @@ public class AnnotationIndexerTest { assertTrue(containsSymbol(allSymbols, "@/mapping-subpackage -- (no method defined)", uriPrefix + "/src/main/java/org/test/sub/MappingClassSubpackage.java", 7, 1, 7, 38)); } + @Test + public void testRetrievingSymbolsPerDocument() throws Exception { + AnnotationIndexer indexer = new AnnotationIndexer(projectFinder, symbolProviders); + File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()); + indexer.scanFiles(directory); + + String uriPrefix = "file://" + directory.getAbsolutePath(); + List symbols = indexer.getSymbols(uriPrefix + "/src/main/java/org/test/MainClass.java"); + assertEquals(4, symbols.size()); + assertTrue(containsSymbol(symbols, "@SpringBootApplication", uriPrefix + "/src/main/java/org/test/MainClass.java", 6, 0, 6, 22)); + assertTrue(containsSymbol(symbols, "@/embedded-foo-mapping -- (no method defined)", uriPrefix + "/src/main/java/org/test/MainClass.java", 17, 1, 17, 41)); + assertTrue(containsSymbol(symbols, "@/foo-root-mapping -- (no method defined)", uriPrefix + "/src/main/java/org/test/MainClass.java", 24, 0, 24, 36)); + assertTrue(containsSymbol(symbols, "@/embedded-foo-mapping -- (no method defined)", uriPrefix + "/src/main/java/org/test/MainClass.java", 27, 1, 27, 41)); + + symbols = indexer.getSymbols(uriPrefix + "/src/main/java/org/test/SimpleMappingClass.java"); + assertEquals(2, symbols.size()); + assertTrue(containsSymbol(symbols, "@/mapping1 -- (no method defined)", uriPrefix + "/src/main/java/org/test/SimpleMappingClass.java", 6, 1, 6, 28)); + assertTrue(containsSymbol(symbols, "@/mapping2 -- (no method defined)", uriPrefix + "/src/main/java/org/test/SimpleMappingClass.java", 11, 1, 11, 28)); + + symbols = indexer.getSymbols(uriPrefix + "/src/main/java/org/test/sub/MappingClassSubpackage.java"); + assertEquals(2, symbols.size()); + assertTrue(containsSymbol(symbols, "@/classlevel -- (no method defined)", uriPrefix + "/src/main/java/org/test/sub/MappingClassSubpackage.java", 4, 0, 4, 30)); + assertTrue(containsSymbol(symbols, "@/mapping-subpackage -- (no method defined)", uriPrefix + "/src/main/java/org/test/sub/MappingClassSubpackage.java", 7, 1, 7, 38)); + } + @Test public void testScanningAllAnnotationsMultiModuleProjectUpfront() throws Exception { AnnotationIndexer indexer = new AnnotationIndexer(projectFinder, symbolProviders);