first version of re-introduced content-assist for spring data repositories

This commit is contained in:
Martin Lippert
2018-11-13 21:18:50 +01:00
parent 84825fb7b4
commit 58cdc2d703
14 changed files with 372 additions and 79 deletions

View File

@@ -26,6 +26,7 @@ import org.springframework.ide.vscode.boot.java.autowired.AutowiredHoverProvider
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.conditionals.ConditionalsLiveHoverProvider;
import org.springframework.ide.vscode.boot.java.data.DataRepositoryCompletionProcessor;
import org.springframework.ide.vscode.boot.java.data.DataRepositorySymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.BootJavaCodeLensEngine;
import org.springframework.ide.vscode.boot.java.handlers.BootJavaCompletionEngine;
@@ -257,45 +258,44 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
protected ICompletionEngine createCompletionEngine(
JavaProjectFinder javaProjectFinder,
SpringPropertyIndexProvider indexProvider,
SpringPropertyIndexProvider adHocIndexProvider
) {
SpringPropertyIndexProvider adHocIndexProvider)
{
Map<String, CompletionProvider> providers = new HashMap<>();
providers.put(org.springframework.ide.vscode.boot.java.scope.Constants.SPRING_SCOPE,
new ScopeCompletionProcessor());
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE,
new ValueCompletionProcessor(indexProvider, adHocIndexProvider));
providers.put(org.springframework.ide.vscode.boot.java.scope.Constants.SPRING_SCOPE, new ScopeCompletionProcessor());
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueCompletionProcessor(indexProvider, adHocIndexProvider));
providers.put(Annotations.REPOSITORY, new DataRepositoryCompletionProcessor());
JavaSnippetManager snippetManager = new JavaSnippetManager(server::createSnippetBuilder);
snippetManager.add(
new JavaSnippet("RequestMapping method", JavaSnippetContext.BOOT_MEMBERS, CompletionItemKind.Method,
ImmutableList.of("org.springframework.web.bind.annotation.RequestMapping",
"org.springframework.web.bind.annotation.RequestMethod",
"org.springframework.web.bind.annotation.RequestParam"),
"@RequestMapping(value=\"${path}\", method=RequestMethod.${GET})\n"
+ "public ${SomeData} ${requestMethodName}(@RequestParam ${String} ${param}) {\n"
+ " return new ${SomeData}(${cursor});\n" + "}\n"));
snippetManager
.add(new JavaSnippet("GetMapping method", JavaSnippetContext.BOOT_MEMBERS, CompletionItemKind.Method,
ImmutableList.of("org.springframework.web.bind.annotation.GetMapping",
"org.springframework.web.bind.annotation.RequestParam"),
"@GetMapping(value=\"${path}\")\n"
+ "public ${SomeData} ${getMethodName}(@RequestParam ${String} ${param}) {\n"
+ " return new ${SomeData}(${cursor});\n" + "}\n"));
snippetManager.add(new JavaSnippet("PostMapping method", JavaSnippetContext.BOOT_MEMBERS,
CompletionItemKind.Method,
ImmutableList.of("org.springframework.web.bind.annotation.PostMapping",
"org.springframework.web.bind.annotation.RequestBody"),
"@PostMapping(value=\"${path}\")\n"
+ "public ${SomeEnityData} ${postMethodName}(@RequestBody ${SomeEnityData} ${entity}) {\n"
+ " //TODO: process POST request\n" + " ${cursor}\n" + " return ${entity};\n" + "}\n"));
snippetManager.add(new JavaSnippet("PutMapping method", JavaSnippetContext.BOOT_MEMBERS,
CompletionItemKind.Method,
ImmutableList.of("org.springframework.web.bind.annotation.PutMapping",
"org.springframework.web.bind.annotation.RequestBody",
"org.springframework.web.bind.annotation.PathVariable"),
"@PutMapping(value=\"${path}/{${id}}\")\n"
+ "public ${SomeEnityData} ${putMethodName}(@PathVariable ${pvt:String} ${id}, @RequestBody ${SomeEnityData} ${entity}) {\n"
+ " //TODO: process PUT request\n" + " ${cursor}\n" + " return ${entity};\n" + "}"));
// snippetManager.add(
// new JavaSnippet("RequestMapping method", JavaSnippetContext.BOOT_MEMBERS, CompletionItemKind.Method,
// ImmutableList.of("org.springframework.web.bind.annotation.RequestMapping",
// "org.springframework.web.bind.annotation.RequestMethod",
// "org.springframework.web.bind.annotation.RequestParam"),
// "@RequestMapping(value=\"${path}\", method=RequestMethod.${GET})\n"
// + "public ${SomeData} ${requestMethodName}(@RequestParam ${String} ${param}) {\n"
// + " return new ${SomeData}(${cursor});\n" + "}\n"));
// snippetManager
// .add(new JavaSnippet("GetMapping method", JavaSnippetContext.BOOT_MEMBERS, CompletionItemKind.Method,
// ImmutableList.of("org.springframework.web.bind.annotation.GetMapping",
// "org.springframework.web.bind.annotation.RequestParam"),
// "@GetMapping(value=\"${path}\")\n"
// + "public ${SomeData} ${getMethodName}(@RequestParam ${String} ${param}) {\n"
// + " return new ${SomeData}(${cursor});\n" + "}\n"));
// snippetManager.add(new JavaSnippet("PostMapping method", JavaSnippetContext.BOOT_MEMBERS,
// CompletionItemKind.Method,
// ImmutableList.of("org.springframework.web.bind.annotation.PostMapping",
// "org.springframework.web.bind.annotation.RequestBody"),
// "@PostMapping(value=\"${path}\")\n"
// + "public ${SomeEnityData} ${postMethodName}(@RequestBody ${SomeEnityData} ${entity}) {\n"
// + " //TODO: process POST request\n" + " ${cursor}\n" + " return ${entity};\n" + "}\n"));
// snippetManager.add(new JavaSnippet("PutMapping method", JavaSnippetContext.BOOT_MEMBERS,
// CompletionItemKind.Method,
// ImmutableList.of("org.springframework.web.bind.annotation.PutMapping",
// "org.springframework.web.bind.annotation.RequestBody",
// "org.springframework.web.bind.annotation.PathVariable"),
// "@PutMapping(value=\"${path}/{${id}}\")\n"
// + "public ${SomeEnityData} ${putMethodName}(@PathVariable ${pvt:String} ${id}, @RequestBody ${SomeEnityData} ${entity}) {\n"
// + " //TODO: process PUT request\n" + " ${cursor}\n" + " return ${entity};\n" + "}"));
return new BootJavaCompletionEngine(this, providers, snippetManager);
}

View File

@@ -0,0 +1,17 @@
/*******************************************************************************
* Copyright (c) 2018 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.data;
public class Constants {
public static final String REPOSITORY_TYPE = "org.springframework.data.repository.Repository";
}

View File

@@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright (c) 2018 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.data;
import java.util.Collection;
import java.util.Optional;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.CompletionItemKind;
import org.springframework.ide.vscode.boot.java.handlers.CompletionProvider;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* @author Martin Lippert
*/
public class DataRepositoryCompletionProcessor implements CompletionProvider {
@Override
public void provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type,
int offset, IDocument doc, Collection<ICompletionProposal> completions) {
}
@Override
public void provideCompletions(ASTNode node, int offset, IDocument doc, Collection<ICompletionProposal> completions) {
TypeDeclaration type = ASTUtils.findDeclaringType(node);
DataRepositoryDefinition repo = getDataRepositoryDefinition(type);
if (repo != null) {
DocumentEdits edits = new DocumentEdits(null);
edits.insert(offset, "List<Customer> findByLastName${1|(String lastName);,And,Or|}");
DocumentEdits additionalEdits = new DocumentEdits(null);
// additionalEdits.insert(offset, "(String lastName);");
completions.add(new FindByCompletionProposal("findByLastName(String lastName);", CompletionItemKind.Method, edits, null, null, Optional.of(additionalEdits)));
System.out.println("data completion proposal calculation for: " + node.toString());
}
}
private DataRepositoryDefinition getDataRepositoryDefinition(TypeDeclaration type) {
if (type != null) {
ITypeBinding resolvedType = type.resolveBinding();
return getDataRepositoryDefinition(type, resolvedType);
}
return null;
}
private DataRepositoryDefinition getDataRepositoryDefinition(TypeDeclaration type, ITypeBinding resolvedType) {
if (resolvedType != null) {
// interface analysis
ITypeBinding[] interfaces = resolvedType.getInterfaces();
for (ITypeBinding resolvedInterface : interfaces) {
String simplifiedType = null;
if (resolvedInterface.isParameterizedType()) {
simplifiedType = resolvedInterface.getBinaryName();
}
else {
simplifiedType = resolvedType.getQualifiedName();
}
if (Constants.REPOSITORY_TYPE.equals(simplifiedType)) {
return new DataRepositoryDefinition();
}
else {
DataRepositoryDefinition repo = getDataRepositoryDefinition(type, resolvedInterface);
if (repo != null) {
return repo;
}
}
}
// super type analysis
ITypeBinding superclass = resolvedType.getSuperclass();
if (superclass != null) {
return getDataRepositoryDefinition(type, superclass);
}
}
return null;
}
}

View File

@@ -0,0 +1,15 @@
/*******************************************************************************
* Copyright (c) 2018 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.data;
public class DataRepositoryDefinition {
}

View File

@@ -36,8 +36,6 @@ import reactor.util.function.Tuples;
* @author Martin Lippert
*/
public class DataRepositorySymbolProvider implements SymbolProvider {
private static final String REPOSITORY_TYPE = "org.springframework.data.repository.Repository";
@Override
public Collection<EnhancedSymbolInformation> getSymbols(TypeDeclaration typeDeclaration, TextDocument doc) {
@@ -96,10 +94,10 @@ public class DataRepositorySymbolProvider implements SymbolProvider {
simplifiedType = resolvedType.getQualifiedName();
}
if (REPOSITORY_TYPE.equals(simplifiedType)) {
if (Constants.REPOSITORY_TYPE.equals(simplifiedType)) {
String beanName = getBeanName(typeDeclaration);
String beanType = resolvedInterface.getName();
String domainType = null;
if (resolvedInterface.isParameterizedType()) {
ITypeBinding[] typeParameters = resolvedInterface.getTypeArguments();

View File

@@ -0,0 +1,77 @@
/*******************************************************************************
* Copyright (c) 2018 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.data;
import java.util.Optional;
import org.eclipse.lsp4j.CompletionItemKind;
import org.eclipse.lsp4j.InsertTextFormat;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public class FindByCompletionProposal implements ICompletionProposal {
private String label;
private CompletionItemKind kind;
private DocumentEdits edits;
private String details;
private Renderable doc;
private Optional<DocumentEdits> additionalEdits;
public FindByCompletionProposal(String label, CompletionItemKind kind, DocumentEdits edits, String details,
Renderable doc, Optional<DocumentEdits> additionalEdits) {
super();
this.label = label;
this.kind = kind;
this.edits = edits;
this.details = details;
this.doc = doc;
this.additionalEdits = additionalEdits;
}
@Override
public String getLabel() {
return label;
}
@Override
public CompletionItemKind getKind() {
return kind;
}
@Override
public DocumentEdits getTextEdit() {
return edits;
}
@Override
public String getDetail() {
return details;
}
@Override
public Renderable getDocumentation() {
return doc;
}
@Override
public Optional<DocumentEdits> getAdditionalEdit() {
return additionalEdits;
}
@Override
public InsertTextFormat getInsertTextFormat() {
return InsertTextFormat.Snippet;
}
}

View File

@@ -49,8 +49,9 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
if (node != null) {
Collection<ICompletionProposal> completions = new ArrayList<ICompletionProposal>();
completions.addAll(collectCompletionsForAnnotations(node, offset, document));
completions.addAll(snippets.getCompletions(document, offset, node, cu));
collectCompletionsForAnnotations(node, offset, document, completions);
collectCompletions(node, offset, document, completions);
snippets.getCompletions(document, offset, node, cu, completions);
return completions;
}
}
@@ -59,7 +60,7 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
});
}
private Collection<ICompletionProposal> collectCompletionsForAnnotations(ASTNode node, int offset, IDocument doc) {
private void collectCompletionsForAnnotations(ASTNode node, int offset, IDocument doc, Collection<ICompletionProposal> completions) {
Annotation annotation = null;
ASTNode exactNode = node;
@@ -75,13 +76,19 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
if (qualifiedName != null) {
CompletionProvider provider = this.completionProviders.get(qualifiedName);
if (provider != null) {
return provider.provideCompletions(exactNode, annotation, type, offset, doc);
provider.provideCompletions(exactNode, annotation, type, offset, doc, completions);
}
}
}
}
}
return Collections.emptyList();
private void collectCompletions(ASTNode node, int offset, TextDocument document, Collection<ICompletionProposal> completions) {
if (node != null) {
for (CompletionProvider completionProvider : this.completionProviders.values()) {
completionProvider.provideCompletions(node, offset, document, completions);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2018 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
@@ -23,6 +23,7 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
*/
public interface CompletionProvider {
Collection<ICompletionProposal> provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type, int offset, IDocument doc);
void provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type, int offset, IDocument doc, Collection<ICompletionProposal> completions);
void provideCompletions(ASTNode node, int offset, IDocument doc, Collection<ICompletionProposal> completions);
}

View File

@@ -10,9 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.scope;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
@@ -30,10 +28,8 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
public class ScopeCompletionProcessor implements CompletionProvider {
@Override
public Collection<ICompletionProposal> provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type,
int offset, IDocument doc) {
List<ICompletionProposal> result = new ArrayList<>();
public void provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type,
int offset, IDocument doc, Collection<ICompletionProposal> completions) {
try {
if (node instanceof SimpleName && node.getParent() instanceof MemberValuePair) {
@@ -43,7 +39,7 @@ public class ScopeCompletionProcessor implements CompletionProvider {
if ("value".equals(memberPair.getName().toString()) && memberPair.getValue().toString().equals("$missing$")) {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, offset, offset, "");
result.add(proposal);
completions.add(proposal);
}
}
}
@@ -51,7 +47,7 @@ public class ScopeCompletionProcessor implements CompletionProvider {
else if (node == annotation && doc.get(offset - 1, 2).endsWith("()")) {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, offset, offset, "");
result.add(proposal);
completions.add(proposal);
}
}
else if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
@@ -61,7 +57,7 @@ public class ScopeCompletionProcessor implements CompletionProvider {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
if (completion.getValue().startsWith(prefix)) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, node.getStartPosition(), node.getStartPosition() + node.getLength(), prefix);
result.add(proposal);
completions.add(proposal);
}
}
}
@@ -75,7 +71,7 @@ public class ScopeCompletionProcessor implements CompletionProvider {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
if (completion.getValue().startsWith(prefix)) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, node.getStartPosition(), node.getStartPosition() + node.getLength(), prefix);
result.add(proposal);
completions.add(proposal);
}
}
}
@@ -84,8 +80,10 @@ public class ScopeCompletionProcessor implements CompletionProvider {
catch (Exception e) {
e.printStackTrace();
}
}
return result;
@Override
public void provideCompletions(ASTNode node, int offset, IDocument doc, Collection<ICompletionProposal> completions) {
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2018 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
@@ -47,9 +47,7 @@ public class JavaSnippetManager {
}
public Collection<ICompletionProposal> getCompletions(IDocument doc, int offset, ASTNode node, CompilationUnit cu) {
Collection<ICompletionProposal> completions = new ArrayList<>();
public void getCompletions(IDocument doc, int offset, ASTNode node, CompilationUnit cu, Collection<ICompletionProposal> completions) {
DocumentRegion query = PREFIX_FINDER.getPrefixRegion(doc, offset);
for (JavaSnippet javaSnippet : snippets) {
@@ -58,8 +56,6 @@ public class JavaSnippetManager {
.ifPresent((completion) -> completions.add(completion));
}
}
return completions;
}
}

View File

@@ -12,7 +12,6 @@ package org.springframework.ide.vscode.boot.java.value;
import static org.springframework.ide.vscode.commons.util.StringUtil.camelCaseToHyphens;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -49,10 +48,8 @@ public class ValueCompletionProcessor implements CompletionProvider {
}
@Override
public Collection<ICompletionProposal> provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type,
int offset, IDocument doc) {
List<ICompletionProposal> result = new ArrayList<>();
public void provideCompletions(ASTNode node, Annotation annotation, ITypeBinding type,
int offset, IDocument doc, Collection<ICompletionProposal> completions) {
try {
// case: @Value(<*>)
@@ -69,40 +66,42 @@ public class ValueCompletionProcessor implements CompletionProvider {
// if it cannot resolve it. If sending this as plain text, then insertion happens correctly
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match, InsertTextFormat.PlainText);
result.add(proposal);
completions.add(proposal);
}
}
// case: @Value(prefix<*>)
else if (node instanceof SimpleName && node.getParent() instanceof Annotation) {
computeProposalsForSimpleName(node, result, offset, doc);
computeProposalsForSimpleName(node, completions, offset, doc);
}
// case: @Value(value=<*>)
else if (node instanceof SimpleName && node.getParent() instanceof MemberValuePair
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
computeProposalsForSimpleName(node, result, offset, doc);
computeProposalsForSimpleName(node, completions, offset, doc);
}
// case: @Value("prefix<*>")
else if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
computeProposalsForStringLiteral(node, result, offset, doc);
computeProposalsForStringLiteral(node, completions, offset, doc);
}
}
// case: @Value(value="prefix<*>")
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
computeProposalsForStringLiteral(node, result, offset, doc);
computeProposalsForStringLiteral(node, completions, offset, doc);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return result;
}
private void computeProposalsForSimpleName(ASTNode node, List<ICompletionProposal> completions, int offset,
@Override
public void provideCompletions(ASTNode node, int offset, IDocument doc, Collection<ICompletionProposal> completions) {
}
private void computeProposalsForSimpleName(ASTNode node, Collection<ICompletionProposal> completions, int offset,
IDocument doc) {
String prefix = identifyPropertyPrefix(node.toString(), offset - node.getStartPosition());
@@ -125,7 +124,7 @@ public class ValueCompletionProcessor implements CompletionProvider {
}
}
private void computeProposalsForStringLiteral(ASTNode node, List<ICompletionProposal> completions, int offset,
private void computeProposalsForStringLiteral(ASTNode node, Collection<ICompletionProposal> completions, int offset,
IDocument doc) throws BadLocationException {
String prefix = identifyPropertyPrefix(doc.get(node.getStartPosition() + 1, offset - (node.getStartPosition() + 1)), offset - (node.getStartPosition() + 1));

View File

@@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2018 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.data.test;
import static org.junit.Assert.assertEquals;
import java.io.InputStream;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.CompletionItem;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.HoverTestConf;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.TestAsserts;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Martin Lippert
*/
@RunWith(SpringRunner.class)
@BootLanguageServerTest
@Import(HoverTestConf.class)
public class DataRepositoryCompletionProcessorTest {
@Autowired private BootLanguageServerHarness harness;
private Editor editor;
@Before
public void setup() throws Exception {
IJavaProject testProject = ProjectsHarness.INSTANCE.mavenProject("test-spring-data-symbols");
harness.useProject(testProject);
harness.intialize(null);
}
@Test
public void testStandardFindByCompletions() throws Exception {
prepareCase("{", "{<*>");
assertAnnotationCompletions(
"findByLastName<*>(String lastName);");
}
private void prepareCase(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
InputStream resource = this.getClass().getResourceAsStream("/test-projects/test-spring-data-symbols/src/main/java/org/test/TestCustomerRepositoryForCompletions.java");
String content = IOUtils.toString(resource);
content = content.replace(selectedAnnotation, annotationStatementBeforeTest);
editor = new Editor(harness, content, LanguageId.JAVA);
}
private void assertAnnotationCompletions(String... completedAnnotations) throws Exception {
List<CompletionItem> completions = editor.getCompletions();
int i = 0;
for (String expectedCompleted : completedAnnotations) {
Editor clonedEditor = editor.clone();
clonedEditor.apply(completions.get(i++));
TestAsserts.assertContains(expectedCompleted, clonedEditor.getText());
}
assertEquals(i, completions.size());
}
}

View File

@@ -63,7 +63,7 @@ public class DataRepositorySymbolProviderTest {
}
@Test
public void testSimpleReppositorySymbol() throws Exception {
public void testSimpleRepositorySymbol() throws Exception {
String docUri = directory.toPath().resolve("src/main/java/org/test/CustomerRepository.java").toUri().toString();
List<? extends SymbolInformation> symbols = indexer.getSymbols(docUri);
assertEquals(1, symbols.size());

View File

@@ -0,0 +1,8 @@
package org.test;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface TestCustomerRepositoryForCompletions extends CrudRepository<Customer, Long> {
}