Split vscode-boot-java to separate out language-server

This commit is contained in:
Kris De Volder
2017-04-07 14:36:23 -07:00
parent 712e14ded4
commit 95355ff981
67 changed files with 108 additions and 955 deletions

View File

@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2016, 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;
import org.eclipse.lsp4j.CompletionOptions;
import org.eclipse.lsp4j.ServerCapabilities;
import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.springframework.ide.vscode.boot.java.completions.BootJavaCompletionEngine;
import org.springframework.ide.vscode.boot.java.completions.BootJavaReconcileEngine;
import org.springframework.ide.vscode.boot.java.hover.BootJavaHoverProvider;
import org.springframework.ide.vscode.boot.java.references.BootJavaReferencesHandler;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.java.DefaultJavaProjectFinder;
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.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.maven.JavaProjectWithClasspathFileFinderStrategy;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* Language Server for Spring Boot Application Properties files
*
* @author Martin Lippert
*/
public class BootJavaLanguageServer extends SimpleLanguageServer {
public static final JavaProjectFinder DEFAULT_PROJECT_FINDER = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {
new MavenProjectFinderStrategy(MavenCore.getDefault()),
new GradleProjectFinderStrategy(GradleCore.getDefault()),
new JavaProjectWithClasspathFileFinderStrategy()
});
private final VscodeCompletionEngineAdapter completionEngine;
public BootJavaLanguageServer(JavaProjectFinder javaProjectFinder, SpringPropertyIndexProvider indexProvider) {
SimpleTextDocumentService documents = getTextDocumentService();
IReconcileEngine reconcileEngine = new BootJavaReconcileEngine();
documents.onDidChangeContent(params -> {
TextDocument doc = params.getDocument();
validateWith(doc, reconcileEngine);
});
ICompletionEngine bootCompletionEngine = new BootJavaCompletionEngine(javaProjectFinder, indexProvider);
completionEngine = new VscodeCompletionEngineAdapter(this, bootCompletionEngine);
completionEngine.setMaxCompletionsNumber(100);
documents.onCompletion(completionEngine::getCompletions);
documents.onCompletionResolve(completionEngine::resolveCompletion);
HoverHandler hoverInfoProvider = new BootJavaHoverProvider(this, javaProjectFinder);
documents.onHover(hoverInfoProvider);
ReferencesHandler referencesHandler = new BootJavaReferencesHandler(this, javaProjectFinder);
documents.onRefeences(referencesHandler);
}
public void setMaxCompletionsNumber(int number) {
completionEngine.setMaxCompletionsNumber(number);
}
@Override
protected ServerCapabilities getServerCapabilities() {
ServerCapabilities c = new ServerCapabilities();
c.setTextDocumentSync(TextDocumentSyncKind.Incremental);
CompletionOptions completionProvider = new CompletionOptions();
completionProvider.setResolveProvider(false);
c.setCompletionProvider(completionProvider);
c.setHoverProvider(true);
c.setReferencesProvider(true);
return c;
}
}

View File

@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2016, 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;
import java.io.IOException;
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.languageserver.LaunguageServerApp;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
/**
* Starts up Language Server process
*
* @author Martin Lippert
*/
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
LaunguageServerApp.start(() -> {
JavaProjectFinder javaProjectFinder = BootJavaLanguageServer.DEFAULT_PROJECT_FINDER;
DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
SimpleLanguageServer server = new BootJavaLanguageServer(javaProjectFinder, indexProvider);
return server;
});
}
}

View File

@@ -0,0 +1,126 @@
/*******************************************************************************
* 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.completions;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
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.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* @author Martin Lippert
*/
public class BootJavaCompletionEngine implements ICompletionEngine {
private static final String SPRING_SCOPE = "org.springframework.context.annotation.Scope";
private static final String SPRING_VALUE = "org.springframework.beans.factory.annotation.Value";
private JavaProjectFinder projectFinder;
private SpringPropertyIndexProvider indexProvider;
public BootJavaCompletionEngine(JavaProjectFinder projectFinder, SpringPropertyIndexProvider indexProvider) {
this.projectFinder = projectFinder;
this.indexProvider = indexProvider;
}
@Override
public Collection<ICompletionProposal> getCompletions(IDocument document, int offset) throws Exception {
List<ICompletionProposal> completions = new ArrayList<>();
ASTParser parser = ASTParser.newParser(AST.JLS8);
Map<String, String> 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);
ASTNode node = NodeFinder.perform(cu, offset, 0);
if (node != null) {
collectCompletionsForAnnotations(node, completions, offset, document);
}
System.out.println("AST node found: " + node.getClass().getName());
return completions;
}
private void collectCompletionsForAnnotations(ASTNode node, List<ICompletionProposal> completions, int offset, IDocument doc) {
Annotation annotation = null;
ASTNode exactNode = node;
while (node != null && !(node instanceof Annotation)) {
node = node.getParent();
}
if (node != null) {
annotation = (Annotation) node;
ITypeBinding type = annotation.resolveTypeBinding();
if (type != null) {
String qualifiedName = type.getQualifiedName();
if (qualifiedName != null && qualifiedName.startsWith("org.springframework")) {
collectCompletionsForSpringAnnotation(exactNode, annotation, type, completions, offset, doc);
}
}
}
}
private void collectCompletionsForSpringAnnotation(ASTNode node, Annotation annotation, ITypeBinding type,
List<ICompletionProposal> completions, int offset, IDocument doc) {
if (type.getQualifiedName().equals(SPRING_SCOPE)) {
new ScopeCompletionProcessor().collectCompletionsForScopeAnnotation(node, annotation, type, completions, offset, doc);
}
else if (type.getQualifiedName().equals(SPRING_VALUE)) {
new ValueCompletionProcessor(indexProvider.getIndex(doc)).collectCompletionsForValueAnnotation(node, annotation, type, completions, offset, doc);
}
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(doc);
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
}
}

View File

@@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2016-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.completions;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* @author Martin Lippert
*/
public class BootJavaReconcileEngine implements IReconcileEngine {
@Override
public void reconcile(IDocument doc, IProblemCollector problemCollector) {
}
}

View File

@@ -0,0 +1,83 @@
/*******************************************************************************
* 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.completions;
import java.util.List;
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.MemberValuePair;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* @author Martin Lippert
*/
public class ScopeCompletionProcessor {
public void collectCompletionsForScopeAnnotation(ASTNode node, Annotation annotation, ITypeBinding type,
List<ICompletionProposal> completions, int offset, IDocument doc) {
try {
if (node instanceof SimpleName && node.getParent() instanceof MemberValuePair) {
MemberValuePair memberPair = (MemberValuePair) node.getParent();
// case: @Scope(value=<*>)
if ("value".equals(memberPair.getName().toString()) && memberPair.getValue().toString().equals("$missing$")) {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, offset, offset, "");
completions.add(proposal);
}
}
}
// case: @Scope(<*>)
else if (node == annotation && doc.get(offset - 1, 2).endsWith("()")) {
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, offset, offset, "");
completions.add(proposal);
}
}
else if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
// case: @Scope("...")
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
String prefix = doc.get(node.getStartPosition(), offset - node.getStartPosition());
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
if (completion.getValue().startsWith(prefix)) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, node.getStartPosition(), node.getStartPosition() + node.getLength(), prefix);
completions.add(proposal);
}
}
}
}
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair) {
MemberValuePair memberPair = (MemberValuePair) node.getParent();
// case: @Scope(value=<*>)
if ("value".equals(memberPair.getName().toString()) && node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
String prefix = doc.get(node.getStartPosition(), offset - node.getStartPosition());
for (ScopeNameCompletion completion : ScopeNameCompletionProposal.COMPLETIONS) {
if (completion.getValue().startsWith(prefix)) {
ICompletionProposal proposal = new ScopeNameCompletionProposal(completion, doc, node.getStartPosition(), node.getStartPosition() + node.getLength(), prefix);
completions.add(proposal);
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,56 @@
/*******************************************************************************
* 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.completions;
import org.eclipse.lsp4j.CompletionItemKind;
import org.springframework.ide.vscode.commons.util.Renderable;
/**
* @author Martin Lippert
*/
public class ScopeNameCompletion {
private final String label;
private final String detail;
private final Renderable documentation;
private final CompletionItemKind kind;
private final String value;
public ScopeNameCompletion(String value, String label, String detail, Renderable documentation, CompletionItemKind kind) {
super();
this.value = value;
this.label = label;
this.detail = detail;
this.documentation = documentation;
this.kind = kind;
}
public String getLabel() {
return label;
}
public String getDetail() {
return detail;
}
public CompletionItemKind getKind() {
return kind;
}
public Renderable getDocumentation() {
return documentation;
}
public String getValue() {
return this.value;
}
}

View File

@@ -0,0 +1,80 @@
/*******************************************************************************
* 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.completions;
import org.eclipse.lsp4j.CompletionItemKind;
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;
/**
* @author Martin Lippert
*/
public class ScopeNameCompletionProposal implements ICompletionProposal {
public static final ScopeNameCompletion[] COMPLETIONS = new ScopeNameCompletion[] {
new ScopeNameCompletion("\"prototype\"", "prototype", "prototype scope", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"singleton\"", "singleton", "singleton scope (default)", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"request\"", "request", "request scope", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"session\"", "session", "session scope", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"globalSession\"", "globalSession", "globalSession scope", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"application\"", "application", "application scope", null, CompletionItemKind.Value),
new ScopeNameCompletion("\"websocket\"", "websocket", "websocket scope", null, CompletionItemKind.Value)
};
private final IDocument doc;
private final int startOffset;
private final int endOffset;
private final ScopeNameCompletion completion;
private final String prefix;
public ScopeNameCompletionProposal(ScopeNameCompletion completion, IDocument doc, int startOffset, int endOffset, String prefix) {
this.completion = completion;
this.doc = doc;
this.startOffset = startOffset;
this.endOffset = endOffset;
this.prefix = prefix;
}
@Override
public ICompletionProposal deemphasize() {
return null;
}
@Override
public String getLabel() {
return completion.getLabel();
}
@Override
public CompletionItemKind getKind() {
return completion.getKind();
}
@Override
public DocumentEdits getTextEdit() {
DocumentEdits edits = new DocumentEdits(doc);
edits.replace(startOffset + prefix.length(), endOffset, completion.getValue().substring(prefix.length()));
return edits;
}
@Override
public String getDetail() {
return completion.getDetail();
}
@Override
public Renderable getDocumentation() {
return completion.getDocumentation();
}
}

View File

@@ -0,0 +1,180 @@
/*******************************************************************************
* 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.completions;
import static org.springframework.ide.vscode.commons.util.StringUtil.camelCaseToHyphens;
import java.util.List;
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.MemberValuePair;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
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.BadLocationException;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* @author Martin Lippert
*/
public class ValueCompletionProcessor {
private FuzzyMap<ConfigurationMetadataProperty> index;
public ValueCompletionProcessor(FuzzyMap<ConfigurationMetadataProperty> index) {
this.index = index;
}
public void collectCompletionsForValueAnnotation(ASTNode node, Annotation annotation, ITypeBinding type,
List<ICompletionProposal> completions, int offset, IDocument doc) {
try {
// case: @Value(<*>)
if (node == annotation && doc.get(offset - 1, 2).endsWith("()")) {
List<Match<ConfigurationMetadataProperty>> matches = findMatches("");
for (Match<ConfigurationMetadataProperty> match : matches) {
DocumentEdits edits = new DocumentEdits(doc);
edits.replace(offset, offset, "\"${" + match.data.getId() + "}\"");
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
completions.add(proposal);
}
}
// case: @Value(prefix<*>)
else if (node instanceof SimpleName && node.getParent() instanceof Annotation) {
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, completions, offset, doc);
}
// case: @Value("prefix<*>")
else if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
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, completions, offset, doc);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private void computeProposalsForSimpleName(ASTNode node, List<ICompletionProposal> completions, int offset,
IDocument doc) {
String prefix = identifyPropertyPrefix(node.toString(), offset - node.getStartPosition());
int startOffset = node.getStartPosition();
int endOffset = node.getStartPosition() + node.getLength();
String proposalPrefix = "\"";
String proposalPostfix = "\"";
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
for (Match<ConfigurationMetadataProperty> match : matches) {
DocumentEdits edits = new DocumentEdits(doc);
edits.replace(startOffset, endOffset, proposalPrefix + "${" + match.data.getId() + "}" + proposalPostfix);
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
completions.add(proposal);
}
}
private void computeProposalsForStringLiteral(ASTNode node, List<ICompletionProposal> completions, int offset,
IDocument doc) throws BadLocationException {
String prefix = identifyPropertyPrefix(doc.get(node.getStartPosition() + 1, offset - (node.getStartPosition() + 1)), offset - (node.getStartPosition() + 1));
int startOffset = offset - prefix.length();
int endOffset = offset;
String prePrefix = doc.get(node.getStartPosition() + 1, offset - prefix.length() - node.getStartPosition() - 1);
String preCompletion;
if (prePrefix.endsWith("${")) {
preCompletion = "";
}
else if (prePrefix.endsWith("$")) {
preCompletion = "{";
}
else {
preCompletion = "${";
}
String fullNodeContent = doc.get(node.getStartPosition(), node.getLength());
String postCompletion = isClosingBracketMissing(fullNodeContent + preCompletion) ? "}" : "";
List<Match<ConfigurationMetadataProperty>> matches = findMatches(prefix);
for (Match<ConfigurationMetadataProperty> match : matches) {
DocumentEdits edits = new DocumentEdits(doc);
edits.replace(startOffset, endOffset, preCompletion + match.data.getId() + postCompletion);
ValuePropertyKeyProposal proposal = new ValuePropertyKeyProposal(edits, match.data.getId(), match.data.getName(), null);
completions.add(proposal);
}
}
private boolean isClosingBracketMissing(String fullNodeContent) {
int bracketOpens = 0;
for (int i = 0; i < fullNodeContent.length(); i++) {
if (fullNodeContent.charAt(i) == '{') {
bracketOpens++;
}
else if (fullNodeContent.charAt(i) == '}') {
bracketOpens--;
}
}
return bracketOpens > 0;
}
public String identifyPropertyPrefix(String nodeContent, int offset) {
String result = nodeContent.substring(0, offset);
int i = offset - 1;
while (i >= 0) {
char c = nodeContent.charAt(i);
if (c == '}' || c == '{' || c == '$' || c == '#') {
result = result.substring(i + 1, offset);
break;
}
i--;
}
return result;
}
private List<Match<ConfigurationMetadataProperty>> findMatches(String prefix) {
List<Match<ConfigurationMetadataProperty>> matches = index.find(camelCaseToHyphens(prefix));
return matches;
}
}

View File

@@ -0,0 +1,65 @@
/*******************************************************************************
* 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.completions;
import org.eclipse.lsp4j.CompletionItemKind;
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;
/**
* @author Martin Lippert
*/
public class ValuePropertyKeyProposal implements ICompletionProposal {
private DocumentEdits edits;
private String label;
private String detail;
private Renderable documentation;
public ValuePropertyKeyProposal(DocumentEdits edits, String label, String detail, Renderable documentation) {
this.edits = edits;
this.label = label;
this.detail = detail;
this.documentation = documentation;
}
@Override
public ICompletionProposal deemphasize() {
return null;
}
@Override
public String getLabel() {
return this.label;
}
@Override
public CompletionItemKind getKind() {
return CompletionItemKind.Property;
}
@Override
public DocumentEdits getTextEdit() {
return this.edits;
}
@Override
public String getDetail() {
return this.detail;
}
@Override
public Renderable getDocumentation() {
return this.documentation;
}
}

View File

@@ -0,0 +1,140 @@
/*******************************************************************************
* 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.hover;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
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.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.TextDocumentPositionParams;
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.commons.languageserver.util.HoverHandler;
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
*/
public class BootJavaHoverProvider implements HoverHandler {
private static final String SPRING_VALUE = "org.springframework.beans.factory.annotation.Value";
private JavaProjectFinder projectFinder;
private SimpleLanguageServer server;
public BootJavaHoverProvider(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
this.server = server;
this.projectFinder = projectFinder;
}
@Override
public CompletableFuture<Hover> handle(TextDocumentPositionParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.get(params).copy();
if (doc != null) {
try {
int offset = doc.toOffset(params.getPosition());
CompletableFuture<Hover> hoverResult = provideHover(doc, offset);
if (hoverResult != null) {
return hoverResult;
}
}
catch (Exception e) {
}
}
return SimpleTextDocumentService.NO_HOVER;
}
private CompletableFuture<Hover> provideHover(TextDocument document, int offset) throws Exception {
ASTParser parser = ASTParser.newParser(AST.JLS8);
Map<String, String> 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);
ASTNode node = NodeFinder.perform(cu, offset, 0);
if (node != null) {
System.out.println("AST node found: " + node.getClass().getName());
return provideHoverForAnnotation(node, offset, document);
}
return null;
}
private CompletableFuture<Hover> provideHoverForAnnotation(ASTNode node, int offset, TextDocument doc) {
Annotation annotation = null;
ASTNode exactNode = node;
while (node != null && !(node instanceof Annotation)) {
node = node.getParent();
}
if (node != null) {
annotation = (Annotation) node;
ITypeBinding type = annotation.resolveTypeBinding();
if (type != null) {
String qualifiedName = type.getQualifiedName();
if (qualifiedName != null && qualifiedName.startsWith("org.springframework")) {
return provideHoverForSpringAnnotation(exactNode, annotation, type, offset, doc);
}
}
}
return null;
}
private CompletableFuture<Hover> provideHoverForSpringAnnotation(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc) {
if (type.getQualifiedName().equals(SPRING_VALUE)) {
return new ValueHoverProvider().provideHoverForValueAnnotation(node, annotation, type, offset, doc);
}
return null;
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(doc);
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
}
}

View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* 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.hover;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.apache.commons.io.IOUtils;
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.MemberValuePair;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public class ValueHoverProvider {
public CompletableFuture<Hover> provideHoverForValueAnnotation(ASTNode node, Annotation annotation,
ITypeBinding type, int offset, TextDocument doc) {
try {
// case: @Value("prefix<*>")
if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), 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("\"")) {
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private CompletableFuture<Hover> provideHover(String value, int offset, int nodeStartOffset, TextDocument doc) {
try {
LocalRange range = getPropertyRange(value, offset);
if (range != null) {
String propertyKey = value.substring(range.getStart(), range.getEnd());
JSONObject properties = getPropertiesFromProcess();
if (propertyKey != null && properties != null) {
Iterator<?> keys = properties.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
JSONObject props = properties.getJSONObject(key);
if (props.has(propertyKey)) {
String propertyValue = props.getString(propertyKey);
Range hoverRange = doc.toRange(nodeStartOffset + range.getStart(), range.getEnd() - range.getStart());
Hover hover = new Hover();
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
hoverContent.add(Either.forLeft("property value for " + propertyKey));
hoverContent.add(Either.forLeft(propertyValue));
hoverContent.add(Either.forLeft("coming from:"));
hoverContent.add(Either.forLeft(key));
hover.setContents(hoverContent);
hover.setRange(hoverRange);
return CompletableFuture.completedFuture(hover);
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public JSONObject getPropertiesFromProcess() {
try {
URL url = new URL("http://localhost:8080/env");
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String body = IOUtils.toString(in, encoding);
JSONTokener tokener = new JSONTokener(body);
JSONObject jsonData = new JSONObject(tokener);
return jsonData;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String getPropertyKey(String value, int offset) {
LocalRange range = getPropertyRange(value, offset);
if (range != null) {
return value.substring(range.getStart(), range.getEnd());
}
return null;
}
public LocalRange getPropertyRange(String value, int offset) {
int start = -1;
int end = -1;
for (int i = offset - 1; i >= 0; i--) {
if (value.charAt(i) == '{') {
start = i + 1;
break;
}
else if (value.charAt(i) == '}') {
break;
}
}
for(int i = offset; i < value.length(); i++) {
if (value.charAt(i) == '{' || value.charAt(i) == '$') {
break;
}
else if (value.charAt(i) == '}') {
end = i;
break;
}
}
if (start > 0 && start < value.length() && end > 0 && end <= value.length() && start < end) {
return new LocalRange(start, end);
}
return null;
}
public static class LocalRange {
private int start;
private int end;
public LocalRange(int start, int end) {
this.start = start;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
}
}

View File

@@ -0,0 +1,141 @@
/*******************************************************************************
* 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.references;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
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.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.ReferenceParams;
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.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.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
* @author Martin Lippert
*/
public class BootJavaReferencesHandler implements ReferencesHandler {
private static final String SPRING_VALUE = "org.springframework.beans.factory.annotation.Value";
private JavaProjectFinder projectFinder;
private SimpleLanguageServer server;
public BootJavaReferencesHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
this.server = server;
this.projectFinder = projectFinder;
}
@Override
public CompletableFuture<List<? extends Location>> handle(ReferenceParams params) {
SimpleTextDocumentService documents = server.getTextDocumentService();
TextDocument doc = documents.get(params).copy();
if (doc != null) {
try {
int offset = doc.toOffset(params.getPosition());
CompletableFuture<List<? extends Location>> referencesResult = provideReferences(doc, offset);
if (referencesResult != null) {
return referencesResult;
}
}
catch (Exception e) {
}
}
return SimpleTextDocumentService.NO_REFERENCES;
}
private CompletableFuture<List<? extends Location>> provideReferences(TextDocument document, int offset) throws Exception {
ASTParser parser = ASTParser.newParser(AST.JLS8);
Map<String, String> 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);
ASTNode node = NodeFinder.perform(cu, offset, 0);
if (node != null) {
System.out.println("AST node found: " + node.getClass().getName());
return provideReferencesForAnnotation(node, offset, document);
}
return null;
}
private CompletableFuture<List<? extends Location>> provideReferencesForAnnotation(ASTNode node, int offset, TextDocument doc) {
Annotation annotation = null;
ASTNode exactNode = node;
while (node != null && !(node instanceof Annotation)) {
node = node.getParent();
}
if (node != null) {
annotation = (Annotation) node;
ITypeBinding type = annotation.resolveTypeBinding();
if (type != null) {
String qualifiedName = type.getQualifiedName();
if (qualifiedName != null && qualifiedName.startsWith("org.springframework")) {
return provideReferencesForSpringAnnotation(exactNode, annotation, type, offset, doc);
}
}
}
return null;
}
private CompletableFuture<List<? extends Location>> provideReferencesForSpringAnnotation(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc) {
if (type.getQualifiedName().equals(SPRING_VALUE)) {
return new ValuePropertyReferencesProvider(server).provideReferencesForValueAnnotation(node, annotation, type, offset, doc);
}
return null;
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(doc);
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
}
}

View File

@@ -0,0 +1,315 @@
/*******************************************************************************
* 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.references;
import static org.springframework.ide.vscode.commons.yaml.ast.NodeUtil.asScalar;
import java.io.File;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
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.MemberValuePair;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.commons.yaml.ast.YamlASTProvider;
import org.springframework.ide.vscode.commons.yaml.ast.YamlFileAST;
import org.springframework.ide.vscode.commons.yaml.ast.YamlParser;
import org.springframework.ide.vscode.java.properties.antlr.parser.AntlrParser;
import org.springframework.ide.vscode.java.properties.parser.ParseResults;
import org.springframework.ide.vscode.java.properties.parser.Parser;
import org.springframework.ide.vscode.java.properties.parser.PropertiesAst.KeyValuePair;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
/**
* @author Martin Lippert
*/
public class ValuePropertyReferencesProvider {
private SimpleLanguageServer languageServer;
public ValuePropertyReferencesProvider(SimpleLanguageServer languageServer) {
this.languageServer = languageServer;
}
public CompletableFuture<List<? extends Location>> provideReferencesForValueAnnotation(ASTNode node, Annotation annotation,
ITypeBinding type, int offset, TextDocument doc) {
try {
// case: @Value("prefix<*>")
if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), 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("\"")) {
return provideReferences(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private CompletableFuture<List<? extends Location>> provideReferences(String value, int offset, int nodeStartOffset, TextDocument doc) {
try {
LocalRange range = getPropertyRange(value, offset);
if (range != null) {
String propertyKey = value.substring(range.getStart(), range.getEnd());
if (propertyKey != null && propertyKey.length() > 0) {
return findReferencesFromPropertyFiles(languageServer.getWorkspaceRoot(), propertyKey);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public CompletableFuture<List<? extends Location>> findReferencesFromPropertyFiles(Path workspaceRoot,
String propertyKey) {
try (Stream<Path> walk = Files.walk(workspaceRoot)) {
List<Location> locations = walk
.filter(path -> isPropertiesFile(path))
.filter(path -> path.toFile().isFile())
.map(path -> findReferences(path, propertyKey))
.flatMap(Collection::stream)
.collect(Collectors.toList());
return CompletableFuture.completedFuture(locations);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
private boolean isPropertiesFile(Path path) {
Path fileName = path.getFileName();
if (fileName.toString().endsWith(".properties") || path.toString().endsWith(".yml")) {
return fileName.toString().contains("application");
}
else {
return false;
}
}
private List<Location> findReferences(Path path, String propertyKey) {
String filePath = path.toString();
if (filePath.endsWith(".properties")) {
return findReferencesInPropertiesFile(filePath, propertyKey);
}
else if (filePath.endsWith(".yml")) {
return findReferencesInYMLFile(filePath, propertyKey);
}
return new ArrayList<Location>();
}
private List<Location> findReferencesInYMLFile(String filePath, String propertyKey) {
List<Location> foundLocations = new ArrayList<>();
try {
String fileContent = FileUtils.readFileToString(new File(filePath));
Yaml yaml = new Yaml();
YamlASTProvider parser = new YamlParser(yaml);
URI docURI = Paths.get(filePath).toUri();
TextDocument doc = new TextDocument(docURI.toString(), null);
doc.setText(fileContent);
YamlFileAST ast = parser.getAST(doc);
List<Node> nodes = ast.getNodes();
if (nodes != null && !nodes.isEmpty()) {
for (Node node : nodes) {
Node foundNode = findNode(node, "", propertyKey);
if (foundNode != null) {
Position start = new Position();
start.setLine(foundNode.getStartMark().getLine());
start.setCharacter(foundNode.getStartMark().getColumn());
Position end = new Position();
end.setLine(foundNode.getEndMark().getLine());
end.setCharacter(foundNode.getEndMark().getColumn());
Range range = new Range();
range.setStart(start);
range.setEnd(end);
Location location = new Location(docURI.toString(), range);
foundLocations.add(location);
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return foundLocations;
}
protected Node findNode(Node node, String prefix, String propertyKey) {
if (node.getNodeId().equals(NodeId.mapping)) {
for (NodeTuple entry : ((MappingNode)node).getValue()) {
Node keyNode = entry.getKeyNode();
String key = asScalar(keyNode);
String combinedKey = prefix.length() > 0 ? prefix + "." + key : key;
if (combinedKey != null && combinedKey.equals(propertyKey)) {
return keyNode;
}
else {
Node recursive = findNode(entry.getValueNode(), combinedKey, propertyKey);
if (recursive != null) {
return recursive;
}
}
}
}
return null;
}
private List<Location> findReferencesInPropertiesFile(String filePath, String propertyKey) {
List<Location> foundLocations = new ArrayList<>();
try {
String fileContent = FileUtils.readFileToString(new File(filePath));
Parser parser = new AntlrParser();
ParseResults parseResults = parser.parse(fileContent);
if (parseResults != null && parseResults.ast != null) {
parseResults.ast.getNodes(KeyValuePair.class).forEach(pair -> {
if (pair.getKey() != null && pair.getKey().decode().equals(propertyKey)) {
URI docURI = Paths.get(filePath).toUri();
TextDocument doc = new TextDocument(docURI.toString(), null);
doc.setText(fileContent);
try {
int line = doc.getLineOfOffset(pair.getKey().getOffset());
int startInLine = pair.getKey().getOffset() - doc.getLineOffset(line);
int endInLine = startInLine + (pair.getKey().getLength());
Position start = new Position();
start.setLine(line);
start.setCharacter(startInLine);
Position end = new Position();
end.setLine(line);
end.setCharacter(endInLine);
Range range = new Range();
range.setStart(start);
range.setEnd(end);
Location location = new Location(docURI.toString(), range);
foundLocations.add(location);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
return foundLocations;
}
public LocalRange getPropertyRange(String value, int offset) {
int start = -1;
int end = -1;
for (int i = offset - 1; i >= 0; i--) {
if (value.charAt(i) == '{') {
start = i + 1;
break;
}
else if (value.charAt(i) == '}') {
break;
}
}
for(int i = offset; i < value.length(); i++) {
if (value.charAt(i) == '{' || value.charAt(i) == '$') {
break;
}
else if (value.charAt(i) == '}') {
end = i;
break;
}
}
if (start > 0 && start < value.length() && end > 0 && end <= value.length() && start < end) {
return new LocalRange(start, end);
}
return null;
}
public static class LocalRange {
private int start;
private int end;
public LocalRange(int start, int end) {
this.start = start;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
}
}

View File

@@ -0,0 +1,48 @@
/*******************************************************************************
* Copyright (c) 2016, 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.metadata;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexProvider {
private static final FuzzyMap<ConfigurationMetadataProperty> EMPTY_INDEX = new SpringPropertyIndex(null);
private JavaProjectFinder javaProjectFinder;
private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager();
private ProgressService progressService = (id, msg) -> {
/* ignore */ };
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder) {
this.javaProjectFinder = javaProjectFinder;
}
@Override
public FuzzyMap<ConfigurationMetadataProperty> getIndex(IDocument doc) {
IJavaProject jp = javaProjectFinder.find(doc);
if (jp != null) {
return indexManager.get(jp, progressService);
}
return EMPTY_INDEX;
}
public void setProgressService(ProgressService progressService) {
this.progressService = progressService;
}
}

View File

@@ -0,0 +1,147 @@
/*******************************************************************************
* Copyright (c) 2016, 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.metadata;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepositoryJsonBuilder;
import org.springframework.ide.vscode.commons.java.IClasspath;
public class PropertiesLoader {
private static final String MAIN_SPRING_CONFIGURATION_METADATA_JSON = "META-INF/spring-configuration-metadata.json";
public static final String ADDITIONAL_SPRING_CONFIGURATION_METADATA_JSON = "META-INF/additional-spring-configuration-metadata.json";
/**
* The default classpath location for config metadata loaded when scanning .jar files on the classpath.
*/
public static final String[] JAR_META_DATA_LOCATIONS = {
MAIN_SPRING_CONFIGURATION_METADATA_JSON
//Not scanning 'additional' metadata because it integrated already in the main data.
};
/**
* The default classpath location for config metadata loaded when scanning project output folders.
*/
public static final String[] PROJECT_META_DATA_LOCATIONS = {
MAIN_SPRING_CONFIGURATION_METADATA_JSON,
ADDITIONAL_SPRING_CONFIGURATION_METADATA_JSON
};
private static final Logger LOG = Logger.getLogger(PropertiesLoader.class.getName());
private ConfigurationMetadataRepositoryJsonBuilder builder = ConfigurationMetadataRepositoryJsonBuilder.create();
public ConfigurationMetadataRepository load(IClasspath classPath) {
try {
classPath.getClasspathEntries().forEach(entry -> {
File fileEntry = entry.toFile();
if (fileEntry.exists()) {
if (fileEntry.isDirectory()) {
loadFromOutputFolder(entry);
} else {
loadFromJar(entry);
}
}
});
} catch (Exception e) {
LOG.log(Level.SEVERE, "Failed to retrieve classpath", e);
}
ConfigurationMetadataRepository repository = builder.build();
return repository;
}
private void loadFromOutputFolder(Path outputFolderPath) {
if (outputFolderPath != null && Files.exists(outputFolderPath)) {
Arrays.stream(PROJECT_META_DATA_LOCATIONS).forEach(mdLoc -> {
loadFromJsonFile(outputFolderPath.resolve(mdLoc));
});
}
}
private void loadFromJsonFile(Path mdf) {
if (Files.exists(mdf)) {
InputStream is = null;
try {
is = Files.newInputStream(mdf);
loadFromInputStream(is);
} catch (Exception e) {
LOG.log(Level.SEVERE, "Error loading file '" + mdf + "'", e);
} finally {
if (is!=null) {
try {
is.close();
} catch (IOException e) {
//ignore
}
}
}
}
}
private void loadFromJar(Path f) {
JarFile jarFile = null;
try {
jarFile = new JarFile(f.toFile());
//jarDump(jarFile);
for (String loc : JAR_META_DATA_LOCATIONS) {
ZipEntry e = jarFile.getEntry(loc);
if (e!=null) {
loadFrom(jarFile, e);
}
}
} catch (Throwable e) {
LOG.log(Level.SEVERE, "Error loading JAR file", e);
} finally {
if (jarFile!=null) {
try {
jarFile.close();
} catch (IOException e) {
}
}
}
}
private void loadFrom(JarFile jarFile, ZipEntry ze) {
InputStream is = null;
try {
is = jarFile.getInputStream(ze);
loadFromInputStream(is);
} catch (Throwable e) {
LOG.log(Level.SEVERE, "Error loading JAR file", e);
} finally {
if (is!=null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
private void loadFromInputStream(InputStream is) throws IOException {
builder.withJsonResource(is);
}
}

View File

@@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2014, 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.metadata;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
/**
* Support for Reconciling, Content Assist and Hover Text in spring properties
* file all make use of a per-project index of spring properties metadata extracted
* from project's classpath. This Index manager is responsible for keeping at most
* one index per-project and to keep the index up-to-date.
*
* @author Kris De Volder
*/
public class SpringPropertiesIndexManager {
private Map<IJavaProject, SpringPropertyIndex> indexes = null;
private static int progressIdCt = 0;
public SpringPropertiesIndexManager() {
}
public synchronized FuzzyMap<ConfigurationMetadataProperty> get(IJavaProject project, ProgressService progressService) {
if (indexes==null) {
indexes = new HashMap<>();
}
SpringPropertyIndex index = indexes.get(project);
if (index==null) {
String progressId = getProgressId();
if (progressService != null) {
progressService.progressEvent(progressId, "Indexing Spring Boot Properties...");
}
index = new SpringPropertyIndex(project.getClasspath());
indexes.put(project, index);
if (progressService != null) {
progressService.progressEvent(progressId, null);
}
}
return index;
}
private static synchronized String getProgressId() {
return DefaultSpringPropertyIndexProvider.class.getName()+ (progressIdCt++);
}
}

View File

@@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2015, 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.metadata;
import java.util.Collection;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
public class SpringPropertyIndex extends FuzzyMap<ConfigurationMetadataProperty> {
public SpringPropertyIndex(IClasspath projectPath) {
if (projectPath!=null) {
PropertiesLoader loader = new PropertiesLoader();
ConfigurationMetadataRepository metadata = loader.load(projectPath);
Collection<ConfigurationMetadataProperty> allEntries = metadata.getAllProperties().values();
for (ConfigurationMetadataProperty item : allEntries) {
add(item);
}
}
}
@Override
protected String getKey(ConfigurationMetadataProperty entry) {
return entry.getId();
}
}

View File

@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2015, 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.metadata;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@FunctionalInterface
public interface SpringPropertyIndexProvider {
FuzzyMap<ConfigurationMetadataProperty> getIndex(IDocument doc);
}

View File

@@ -0,0 +1,182 @@
/*******************************************************************************
* 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.completions.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Callable;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.CompletionItem;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
/**
* @author Martin Lippert
*/
public class ScopeCompletionTest {
private final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject();
private LanguageServerHarness harness;
private PropertyIndexHarness indexHarness;
private IJavaProject testProject;
private Editor editor;
@Before
public void setup() throws Exception {
testProject = ProjectsHarness.INSTANCE.mavenProject("test-annotations");
indexHarness = new PropertyIndexHarness();
harness = new LanguageServerHarness(new Callable<BootJavaLanguageServer>() {
@Override
public BootJavaLanguageServer call() throws Exception {
BootJavaLanguageServer server = new BootJavaLanguageServer(javaProjectFinder, indexHarness.getIndexProvider());
return server;
}
}) {
@Override
protected String getFileExtension() {
return ".java";
}
};
harness.intialize(null);
}
private IJavaProject getTestProject() {
return testProject;
}
@Test
public void testEmptyBracketsCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(<*>)");
assertAnnotationCompletions(
"@Scope(\"prototype\"<*>)",
"@Scope(\"singleton\"<*>)",
"@Scope(\"request\"<*>)",
"@Scope(\"session\"<*>)",
"@Scope(\"globalSession\"<*>)",
"@Scope(\"application\"<*>)",
"@Scope(\"websocket\"<*>)");
}
@Test
public void testEmptyStringLiteralCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(\"<*>\")");
assertAnnotationCompletions(
"@Scope(\"prototype\"<*>)",
"@Scope(\"singleton\"<*>)",
"@Scope(\"request\"<*>)",
"@Scope(\"session\"<*>)",
"@Scope(\"globalSession\"<*>)",
"@Scope(\"application\"<*>)",
"@Scope(\"websocket\"<*>)");
}
@Test
public void testEmptyValueCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(value=<*>)");
assertAnnotationCompletions(
"@Scope(value=\"prototype\"<*>)",
"@Scope(value=\"singleton\"<*>)",
"@Scope(value=\"request\"<*>)",
"@Scope(value=\"session\"<*>)",
"@Scope(value=\"globalSession\"<*>)",
"@Scope(value=\"application\"<*>)",
"@Scope(value=\"websocket\"<*>)");
}
@Test
public void testEmptyValueStringLiteralCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(value=\"<*>\")");
assertAnnotationCompletions(
"@Scope(value=\"prototype\"<*>)",
"@Scope(value=\"singleton\"<*>)",
"@Scope(value=\"request\"<*>)",
"@Scope(value=\"session\"<*>)",
"@Scope(value=\"globalSession\"<*>)",
"@Scope(value=\"application\"<*>)",
"@Scope(value=\"websocket\"<*>)");
}
@Test
public void testPrefixWithClosingQuotesCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(\"pro<*>\")");
assertAnnotationCompletions(
"@Scope(\"prototype\"<*>)");
}
@Test
public void testPrefixWithoutClosingQuotesCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(\"pro<*>)");
assertAnnotationCompletions();
}
@Test
public void testValuePrefixWithClosingQuotesCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(value=\"pro<*>\")");
assertAnnotationCompletions(
"@Scope(value=\"prototype\"<*>)");
}
@Test
public void testValuePrefixWithoutClosingQuotesCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(value=\"pro<*>)");
assertAnnotationCompletions();
}
@Test
public void testPrefixReplaceRestCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(\"pro<*>something\")");
assertAnnotationCompletions(
"@Scope(\"prototype\"<*>)");
}
@Test
public void testDifferentMemberNameCompletion() throws Exception {
prepareCase("@Scope(\"onClass\")", "@Scope(proxyName=\"<*>\")");
assertAnnotationCompletions();
}
private void prepareCase(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
InputStream resource = this.getClass().getResourceAsStream("/test-projects/test-annotations/src/main/java/org/test/TestScopeCompletion.java");
String content = IOUtils.toString(resource);
content = content.replace(selectedAnnotation, annotationStatementBeforeTest);
editor = new Editor(harness, content, "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++));
assertTrue(clonedEditor.getText().contains(expectedCompleted));
}
assertEquals(i, completions.size());
}
}

View File

@@ -0,0 +1,299 @@
/*******************************************************************************
* 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.completions.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Callable;
import org.apache.commons.io.IOUtils;
import org.eclipse.lsp4j.CompletionItem;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.boot.java.completions.ValueCompletionProcessor;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
/**
* @author Martin Lippert
*/
public class ValueCompletionTest {
private final JavaProjectFinder javaProjectFinder = (doc) -> getTestProject();
private LanguageServerHarness harness;
private IJavaProject testProject;
private Editor editor;
private PropertyIndexHarness indexHarness;
@Before
public void setup() throws Exception {
testProject = ProjectsHarness.INSTANCE.mavenProject("test-annotations");
indexHarness = new PropertyIndexHarness();
harness = new LanguageServerHarness(new Callable<BootJavaLanguageServer>() {
@Override
public BootJavaLanguageServer call() throws Exception {
BootJavaLanguageServer server = new BootJavaLanguageServer(javaProjectFinder, indexHarness.getIndexProvider());
return server;
}
}) {
@Override
protected String getFileExtension() {
return ".java";
}
};
harness.intialize(null);
}
private IJavaProject getTestProject() {
return testProject;
}
@Test
public void testPrefixIdentification() {
ValueCompletionProcessor processor = new ValueCompletionProcessor(null);
assertEquals("pre", processor.identifyPropertyPrefix("pre", 3));
assertEquals("pre", processor.identifyPropertyPrefix("prefix", 3));
assertEquals("", processor.identifyPropertyPrefix("", 0));
assertEquals("pre", processor.identifyPropertyPrefix("$pre", 4));
assertEquals("", processor.identifyPropertyPrefix("${pre", 0));
assertEquals("", processor.identifyPropertyPrefix("${pre", 1));
assertEquals("", processor.identifyPropertyPrefix("${pre", 2));
assertEquals("p", processor.identifyPropertyPrefix("${pre", 3));
assertEquals("pr", processor.identifyPropertyPrefix("${pre", 4));
}
@Test
public void testEmptyBracketsCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${data.prop2}\"<*>)",
"@Value(\"${else.prop3}\"<*>)",
"@Value(\"${spring.prop1}\"<*>)");
}
@Test
public void testEmptyBracketsCompletionWithParamName() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(value=<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(value=\"${data.prop2}\"<*>)",
"@Value(value=\"${else.prop3}\"<*>)",
"@Value(value=\"${spring.prop1}\"<*>)");
}
@Test
public void testEmptyBracketsCompletionWithWrongParamName() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(another=<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions();
}
@Test
public void testOnlyDollarNoQoutesCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value($<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${data.prop2}\"<*>)",
"@Value(\"${else.prop3}\"<*>)",
"@Value(\"${spring.prop1}\"<*>)");
}
@Test
public void testOnlyDollarNoQoutesWithParamCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(value=$<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(value=\"${data.prop2}\"<*>)",
"@Value(value=\"${else.prop3}\"<*>)",
"@Value(value=\"${spring.prop1}\"<*>)");
}
@Test
public void testOnlyDollarCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"$<*>\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${data.prop2}<*>\")",
"@Value(\"${else.prop3}<*>\")",
"@Value(\"${spring.prop1}<*>\")");
}
@Test
public void testOnlyDollarWithParamCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(value=\"$<*>\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(value=\"${data.prop2}<*>\")",
"@Value(value=\"${else.prop3}<*>\")",
"@Value(value=\"${spring.prop1}<*>\")");
}
@Test
public void testDollarWithBracketsCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"${<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${data.prop2<*>}\")",
"@Value(\"${else.prop3<*>}\")",
"@Value(\"${spring.prop1<*>}\")");
}
@Test
public void testDollarWithBracketsWithParamCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(value=\"${<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(value=\"${data.prop2<*>}\")",
"@Value(value=\"${else.prop3<*>}\")",
"@Value(value=\"${spring.prop1<*>}\")");
}
@Test
public void testEmptyStringLiteralCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"<*>\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${data.prop2}<*>\")",
"@Value(\"${else.prop3}<*>\")",
"@Value(\"${spring.prop1}<*>\")");
}
@Test
public void testPlainPrefixCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(spri<*>)");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${spring.prop1}\"<*>)");
}
@Test
public void testQoutedPrefixCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"spri<*>\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"${spring.prop1}<*>\")");
}
@Test
public void testRandomSpelExpressionNoCompletion() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{${data.prop2}<*>}\")",
"@Value(\"#{${else.prop3}<*>}\")",
"@Value(\"#{${spring.prop1}<*>}\")");
}
@Test
public void testRandomSpelExpressionWithPropertyDollar() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{345$<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{345${data.prop2}<*>}\")",
"@Value(\"#{345${else.prop3}<*>}\")",
"@Value(\"#{345${spring.prop1}<*>}\")");
}
@Test
public void testRandomSpelExpressionWithPropertyDollerWithoutClosindBracket() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{345${<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{345${data.prop2}<*>}\")",
"@Value(\"#{345${else.prop3}<*>}\")",
"@Value(\"#{345${spring.prop1}<*>}\")");
}
@Test
public void testRandomSpelExpressionWithPropertyDollerWithClosingBracket() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{345${<*>}}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{345${data.prop2<*>}}\")",
"@Value(\"#{345${else.prop3<*>}}\")",
"@Value(\"#{345${spring.prop1<*>}}\")");
}
@Test
public void testRandomSpelExpressionWithPropertyPrefixWithoutClosingBracket() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{345${spri<*>}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{345${spring.prop1}<*>}\")");
}
@Test
public void testRandomSpelExpressionWithPropertyPrefixWithClosingBracket() throws Exception {
prepareCase("@Value(\"onField\")", "@Value(\"#{345${spri<*>}}\")");
prepareDefaultIndexData();
assertAnnotationCompletions(
"@Value(\"#{345${spring.prop1<*>}}\")");
}
private void prepareDefaultIndexData() {
indexHarness.data("spring.prop1", "java.lang.String", null, null);
indexHarness.data("data.prop2", "java.lang.String", null, null);
indexHarness.data("else.prop3", "java.lang.String", null, null);
}
private void prepareCase(String selectedAnnotation, String annotationStatementBeforeTest) throws Exception {
InputStream resource = this.getClass().getResourceAsStream("/test-projects/test-annotations/src/main/java/org/test/TestValueCompletion.java");
String content = IOUtils.toString(resource);
content = content.replace(selectedAnnotation, annotationStatementBeforeTest);
editor = new Editor(harness, content, "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++));
assertTrue(clonedEditor.getText().contains(expectedCompleted));
}
assertEquals(i, completions.size());
}
}

View File

@@ -0,0 +1,52 @@
/*******************************************************************************
* 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.hover.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.hover.ValueHoverProvider;
/**
* @author Martin Lippert
*/
public class ValueHoverTest {
@Test
public void testGetPropertyFromValue() {
ValueHoverProvider provider = new ValueHoverProvider();
assertNull(provider.getPropertyKey("${spring}", 0));
assertNull(provider.getPropertyKey("${spring}", 1));
assertEquals("spring", provider.getPropertyKey("${spring}", 2));
assertEquals("spring", provider.getPropertyKey("${spring}", 3));
assertEquals("spring", provider.getPropertyKey("${spring}", 8));
assertNull(provider.getPropertyKey("${spring}", 9));
assertNull(provider.getPropertyKey("abc ${spring} and other stuff", 0));
assertNull(provider.getPropertyKey("abc ${spring} and other stuff", 5));
assertEquals("spring", provider.getPropertyKey("abc ${spring} and other stuff", 6));
assertEquals("spring", provider.getPropertyKey("abc ${spring} and other stuff", 12));
assertNull(provider.getPropertyKey("abc ${spring} and other stuff", 13));
assertNull(provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 5));
assertEquals("spring", provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 6));
assertEquals("spring", provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 12));
assertNull(provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 13));
assertNull(provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 19));
assertEquals("boot", provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 20));
assertEquals("boot", provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 24));
assertNull(provider.getPropertyKey("abc ${spring} and ${boot} other stuff", 25));
}
}

View File

@@ -0,0 +1,164 @@
/*******************************************************************************
* 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.references.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.eclipse.lsp4j.Location;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.references.ValuePropertyReferencesProvider;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
/**
* @author Martin Lippert
*/
public class PropertyReferenceFinderTest {
@Test
public void testFindReferenceAtBeginningPropFile() throws Exception {
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI());
CompletableFuture<List<? extends Location>> resultFuture = provider.findReferencesFromPropertyFiles(root, "test.property");
assertNotNull(resultFuture);
List<? extends Location> locations = resultFuture.get();
assertEquals(1, locations.size());
Location location = locations.get(0);
URI docURI = Paths.get(root.toString(), "application.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(0, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(0, location.getRange().getEnd().getLine());
assertEquals(13, location.getRange().getEnd().getCharacter());
}
@Test
public void testFindReferenceAtBeginningYMLFile() throws Exception {
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-yml/").toURI());
CompletableFuture<List<? extends Location>> resultFuture = provider.findReferencesFromPropertyFiles(root, "test.property");
assertNotNull(resultFuture);
List<? extends Location> locations = resultFuture.get();
assertEquals(1, locations.size());
Location location = locations.get(0);
URI docURI = Paths.get(root.toString(), "application.yml").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(3, location.getRange().getStart().getLine());
assertEquals(2, location.getRange().getStart().getCharacter());
assertEquals(3, location.getRange().getEnd().getLine());
assertEquals(10, location.getRange().getEnd().getCharacter());
}
@Test
public void testFindReferenceWithinTheDocument() throws Exception {
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/simple-case/").toURI());
CompletableFuture<List<? extends Location>> resultFuture = provider.findReferencesFromPropertyFiles(root, "server.port");
assertNotNull(resultFuture);
List<? extends Location> locations = resultFuture.get();
assertEquals(1, locations.size());
Location location = locations.get(0);
URI docURI = Paths.get(root.toString(), "application.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(2, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(2, location.getRange().getEnd().getLine());
assertEquals(11, location.getRange().getEnd().getCharacter());
}
@Test @Ignore
public void testFindReferenceWithinMultipleFiles() throws Exception {
// TODO: There's something wrong with this test, it fails for me (Kris).
// The 'locations' are not arriving in the expected order.
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/multiple-files/").toURI());
CompletableFuture<List<? extends Location>> resultFuture = provider.findReferencesFromPropertyFiles(root, "appl1.prop");
assertNotNull(resultFuture);
List<? extends Location> locations = resultFuture.get();
assertEquals(3, locations.size());
Location location = locations.get(0);
URI docURI = Paths.get(root.toString(), "application-dev.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(1, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(1, location.getRange().getEnd().getLine());
assertEquals(10, location.getRange().getEnd().getCharacter());
location = locations.get(1);
docURI = Paths.get(root.toString(), "application.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(1, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(1, location.getRange().getEnd().getLine());
assertEquals(10, location.getRange().getEnd().getCharacter());
location = locations.get(2);
docURI = Paths.get(root.toString(), "prod-application.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(1, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(1, location.getRange().getEnd().getLine());
assertEquals(10, location.getRange().getEnd().getCharacter());
}
@Test @Ignore
public void testFindReferenceWithinMultipleMixedFiles() throws Exception {
// TODO: There's something wrong with this test, it fails for me (Kris).
// The 'locations' are not arriving in the expected order.
ValuePropertyReferencesProvider provider = new ValuePropertyReferencesProvider(null);
Path root = Paths.get(ProjectsHarness.class.getResource("/test-property-files/mixed-multiple-files/").toURI());
CompletableFuture<List<? extends Location>> resultFuture = provider.findReferencesFromPropertyFiles(root, "appl1.prop");
assertNotNull(resultFuture);
List<? extends Location> locations = resultFuture.get();
assertEquals(2, locations.size());
Location location = locations.get(0);
URI docURI = Paths.get(root.toString(), "application-dev.properties").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(1, location.getRange().getStart().getLine());
assertEquals(0, location.getRange().getStart().getCharacter());
assertEquals(1, location.getRange().getEnd().getLine());
assertEquals(10, location.getRange().getEnd().getCharacter());
location = locations.get(1);
docURI = Paths.get(root.toString(), "application.yml").toUri();
assertEquals(docURI.toString(), location.getUri());
assertEquals(3, location.getRange().getStart().getLine());
assertEquals(2, location.getRange().getStart().getCharacter());
assertEquals(3, location.getRange().getEnd().getLine());
assertEquals(6, location.getRange().getEnd().getCharacter());
}
}

View File

@@ -0,0 +1,80 @@
/*******************************************************************************
* Copyright (c) 2016, 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.project.harness;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.maven.MavenBuilder;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.maven.java.classpathfile.JavaProjectWithClasspathFile;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Test projects harness
*
* @author Alex Boyko
*/
public class ProjectsHarness {
public static final ProjectsHarness INSTANCE = new ProjectsHarness();;
public Cache<String, IJavaProject> cache = CacheBuilder.newBuilder().concurrencyLevel(1).build();
private enum ProjectType {
MAVEN,
CLASSPATH_TXT
}
private ProjectsHarness() {
}
public IJavaProject project(ProjectType type, String name) throws Exception {
return cache.get(type + "/" + name, () -> {
Path testProjectPath = getProjectPath(name);
switch (type) {
case MAVEN:
MavenBuilder.newBuilder(testProjectPath).clean().pack().javadoc().skipTests().execute();
return new MavenJavaProject(MavenCore.getDefault(), testProjectPath.resolve(MavenCore.POM_XML).toFile());
case CLASSPATH_TXT:
MavenBuilder.newBuilder(testProjectPath).clean().pack().skipTests().execute();
return new JavaProjectWithClasspathFile(testProjectPath.resolve(MavenCore.CLASSPATH_TXT).toFile());
default:
throw new IllegalStateException("Bug!!! Missing case");
}
});
}
protected Path getProjectPath(String name) throws URISyntaxException, IOException {
return getProjectPathFromClasspath(name);
}
private Path getProjectPathFromClasspath(String name) throws URISyntaxException, IOException {
URI resource = ProjectsHarness.class.getResource("/test-projects/" + name).toURI();
return Paths.get(resource);
}
public MavenJavaProject mavenProject(String name) throws Exception {
return (MavenJavaProject) project(ProjectType.MAVEN, name);
}
public IJavaProject javaProjectWithClasspathFile(String name) throws Exception {
return project(ProjectType.CLASSPATH_TXT, name);
}
}

View File

@@ -0,0 +1,562 @@
/*******************************************************************************
* 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.project.harness;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.boot.configurationmetadata.Deprecation;
import org.springframework.boot.configurationmetadata.ValueHint;
import org.springframework.boot.configurationmetadata.ValueProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndex;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
* Provides some convenience apis for test code to create / use test data for a SpringPropertyIndex.
*/
public class PropertyIndexHarness {
private Map<String, ConfigurationMetadataProperty> datas = new LinkedHashMap<>();
private SpringPropertyIndex index = null;
private IJavaProject testProject = null;
protected final SpringPropertyIndexProvider indexProvider = new SpringPropertyIndexProvider() {
@Override
public FuzzyMap<ConfigurationMetadataProperty> getIndex(IDocument doc) {
synchronized (PropertyIndexHarness.this) {
if (index==null) {
IClasspath classpath = testProject == null ? null : testProject.getClasspath();
index = new SpringPropertyIndex(classpath);
for (ConfigurationMetadataProperty propertyInfo : datas.values()) {
index.add(propertyInfo);
}
}
return index;
}
}
};
public synchronized void useProject(IJavaProject p) throws Exception {
index = null;
this.testProject = p;
}
public class ItemConfigurer {
private ConfigurationMetadataProperty item;
public ItemConfigurer(ConfigurationMetadataProperty item) {
this.item = item;
}
/**
* Add a provider with a single parameter.
* @return
*/
public ItemConfigurer provider(String name, String paramName, Object paramValue) {
ValueProvider provider = new ValueProvider();
provider.setName(name);
provider.getParameters().put(paramName, paramValue);
item.getHints().getValueProviders().add(provider);
return this;
}
/**
* Add a value hint. If description contains a '.' the dot is used
* to break description into a short and long description.
* @return
*/
public ItemConfigurer valueHint(Object value, String description) {
ValueHint hint = new ValueHint();
hint.setValue(value);
if (description!=null) {
int dotPos = description.indexOf('.');
if (dotPos>=0) {
hint.setShortDescription( description.substring(0, dotPos));
}
hint.setDescription(description);
}
item.getHints().getValueHints().add(hint);
return this;
}
}
public synchronized ItemConfigurer data(String id, String type, Object deflt, String description,
String... source
) {
ConfigurationMetadataProperty item = new ConfigurationMetadataProperty();
item.setId(id);
item.setDescription(description);
item.setType(type);
item.setDefaultValue(deflt);
index = null;
datas.put(item.getId(), item);
return new ItemConfigurer(item);
}
public synchronized void keyHints(String id, String... hintValues) {
index = null;
List<ValueHint> hints = datas.get(id).getHints().getKeyHints();
for (String value : hintValues) {
ValueHint hint = new ValueHint();
hint.setValue(value);
hints.add(hint);
}
}
public synchronized void valueHints(String id, String... hintValues) {
index = null;
List<ValueHint> hints = datas.get(id).getHints().getValueHints();
for (String value : hintValues) {
ValueHint hint = new ValueHint();
hint.setValue(value);
hints.add(hint);
}
}
public synchronized void deprecate(String key, String replacedBy, String reason) {
index = null;
ConfigurationMetadataProperty info = datas.get(key);
Deprecation d = new Deprecation();
d.setReplacement(replacedBy);
d.setReason(reason);
info.setDeprecation(d);
}
/**
* Call this method to add some default test data to the Completion engine's index.
* Note that this data is not added automatically, some test may want to use smaller
* test data sets.
*/
public void defaultTestData() {
data("banner.charset", "java.nio.charset.Charset", "UTF-8", "Banner file encoding.");
data("banner.location", "java.lang.String", "classpath:banner.txt", "Banner file location.");
data("debug", "java.lang.Boolean", "false", "Enable debug logs.");
data("flyway.check-location", "java.lang.Boolean", "false", "Check that migration scripts location exists.");
data("flyway.clean-on-validation-error", "java.lang.Boolean", null, null);
data("flyway.enabled", "java.lang.Boolean", "true", "Enable flyway.");
data("flyway.encoding", "java.lang.String", null, null);
data("flyway.ignore-failed-future-migration", "java.lang.Boolean", null, null);
data("flyway.init-description", "java.lang.String", null, null);
data("flyway.init-on-migrate", "java.lang.Boolean", null, null);
data("flyway.init-sqls", "java.util.List<java.lang.String>", null, "SQL statements to execute to initialize a connection immediately after obtaining\n it.");
data("flyway.init-version", "org.flywaydb.core.api.MigrationVersion", null, null);
data("flyway.locations", "java.util.List<java.lang.String>", null, "Locations of migrations scripts.");
data("flyway.out-of-order", "java.lang.Boolean", null, null);
data("flyway.password", "java.lang.String", null, "Login password of the database to migrate.");
data("flyway.placeholder-prefix", "java.lang.String", null, null);
data("flyway.placeholders", "java.util.Map<java.lang.String,java.lang.String>", null, null);
data("flyway.placeholder-suffix", "java.lang.String", null, null);
data("flyway.schemas", "java.lang.String[]", null, null);
data("flyway.sql-migration-prefix", "java.lang.String", null, null);
data("flyway.sql-migration-separator", "java.lang.String", null, null);
data("flyway.sql-migration-suffix", "java.lang.String", null, null);
data("flyway.table", "java.lang.String", null, null);
data("flyway.target", "org.flywaydb.core.api.MigrationVersion", null, null);
data("flyway.url", "java.lang.String", null, "JDBC url of the database to migrate. If not set, the primary configured data source\n is used.");
data("flyway.user", "java.lang.String", null, "Login user of the database to migrate.");
data("flyway.validate-on-migrate", "java.lang.Boolean", null, null);
data("http.mappers.json-pretty-print", "java.lang.Boolean", null, "Enable json pretty print.");
data("http.mappers.json-sort-keys", "java.lang.Boolean", null, "Enable key sorting.");
data("liquibase.change-log", "java.lang.String", "classpath:/db/changelog/db.changelog-master.yaml", "Change log configuration path.");
data("liquibase.check-change-log-location", "java.lang.Boolean", "true", "Check the change log location exists.");
data("liquibase.contexts", "java.lang.String", null, "Comma-separated list of runtime contexts to use.");
data("liquibase.default-schema", "java.lang.String", null, "Default database schema.");
data("liquibase.drop-first", "java.lang.Boolean", "false", "Drop the database schema first.");
data("liquibase.enabled", "java.lang.Boolean", "true", "Enable liquibase support.");
data("liquibase.password", "java.lang.String", null, "Login password of the database to migrate.");
data("liquibase.url", "java.lang.String", null, "JDBC url of the database to migrate. If not set, the primary configured data source\n is used.");
data("liquibase.user", "java.lang.String", null, "Login user of the database to migrate.");
data("logging.config", "java.lang.String", null, "Location of the logging configuration file.");
data("logging.file", "java.lang.String", null, "Log file name.");
data("logging.level", "java.util.Map<java.lang.String,java.lang.Object>", null, "Log levels severity mapping. Use 'root' for the root logger.");
data("logging.path", "java.lang.String", null, "Location of the log file.");
data("multipart.file-size-threshold", "java.lang.String", "0", "Threshold after which files will be written to disk. Values can use the suffixed\n \"MB\" or \"KB\" to indicate a Megabyte or Kilobyte size.");
data("multipart.location", "java.lang.String", null, "Intermediate location of uploaded files.");
data("multipart.max-file-size", "java.lang.String", "1Mb", "Max file size. Values can use the suffixed \"MB\" or \"KB\" to indicate a Megabyte or\n Kilobyte size.");
data("multipart.max-request-size", "java.lang.String", "10Mb", "Max request size. Values can use the suffixed \"MB\" or \"KB\" to indicate a Megabyte\n or Kilobyte size.");
data("security.basic.enabled", "java.lang.Boolean", "true", "Enable basic authentication.");
data("security.basic.path", "java.lang.String[]", "[Ljava.lang.Object;@7abd0056", "Comma-separated list of paths to secure.");
data("security.basic.realm", "java.lang.String", "Spring", "HTTP basic realm name.");
data("security.enable-csrf", "java.lang.Boolean", "false", "Enable Cross Site Request Forgery support.");
data("security.filter-order", "java.lang.Integer", "0", "Security filter chain order.");
data("security.headers.cache", "java.lang.Boolean", "false", "Enable cache control HTTP headers.");
data("security.headers.content-type", "java.lang.Boolean", "false", "Enable \"X-Content-Type-Options\" header.");
data("security.headers.frame", "java.lang.Boolean", "false", "Enable \"X-Frame-Options\" header.");
data("security.headers.hsts", "org.springframework.boot.autoconfigure.security.SecurityProperties$Headers$HSTS", null, "HTTP Strict Transport Security (HSTS) mode (none, domain, all).");
data("security.headers.xss", "java.lang.Boolean", "false", "Enable cross site scripting (XSS) protection.");
data("security.ignored", "java.util.List<java.lang.String>", null, "Comma-separated list of paths to exclude from the default secured paths.");
data("security.require-ssl", "java.lang.Boolean", "false", "Enable secure channel for all requests.");
data("security.sessions", "org.springframework.security.config.http.SessionCreationPolicy", null, "Session creation policy (always, never, if_required, stateless).");
data("security.user.name", "java.lang.String", "user", "Default user name.");
data("security.user.password", "java.lang.String", null, "Password for the default user name.");
data("security.user.role", "java.util.List<java.lang.String>", null, "Granted roles for the default user name.");
data("server.address", "java.net.InetAddress", null, "Network address to which the server should bind to.");
data("server.context-parameters", "java.util.Map<java.lang.String,java.lang.String>", null, "ServletContext parameters.");
data("server.context-path", "java.lang.String", null, "Context path of the application.");
data("server.port", "java.lang.Integer", null, "Server HTTP port.");
data("server.servlet-path", "java.lang.String", "/", "Path of the main dispatcher servlet.");
data("server.session-timeout", "java.lang.Integer", null, "Session timeout in seconds.");
data("server.ssl.ciphers", "java.lang.String[]", null, null);
data("server.ssl.client-auth", "org.springframework.boot.context.embedded.Ssl$ClientAuth", null, null);
data("server.ssl.key-alias", "java.lang.String", null, null);
data("server.ssl.key-password", "java.lang.String", null, null);
data("server.ssl.key-store", "java.lang.String", null, null);
data("server.ssl.key-store-password", "java.lang.String", null, null);
data("server.ssl.key-store-provider", "java.lang.String", null, null);
data("server.ssl.key-store-type", "java.lang.String", null, null);
data("server.ssl.protocol", "java.lang.String", null, null);
data("server.ssl.trust-store", "java.lang.String", null, null);
data("server.ssl.trust-store-password", "java.lang.String", null, null);
data("server.ssl.trust-store-provider", "java.lang.String", null, null);
data("server.ssl.trust-store-type", "java.lang.String", null, null);
data("server.tomcat.access-log-enabled", "java.lang.Boolean", "false", "Enable access log.");
data("server.tomcat.access-log-pattern", "java.lang.String", null, "Format pattern for access logs.");
data("server.tomcat.background-processor-delay", "java.lang.Integer", "30", "Delay in seconds between the invocation of backgroundProcess methods.");
data("server.tomcat.basedir", "java.io.File", null, "Tomcat base directory. If not specified a temporary directory will be used.");
data("server.tomcat.internal-proxies", "java.lang.String", "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|169\\.254\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}", "Regular expression that matches proxies that are to be trusted.");
data("server.tomcat.max-http-header-size", "java.lang.Integer", "0", "Maximum size in bytes of the HTTP message header.");
data("server.tomcat.max-threads", "java.lang.Integer", "0", "Maximum amount of worker threads.");
data("server.tomcat.port-header", "java.lang.String", null, "Name of the HTTP header used to override the original port value.");
data("server.tomcat.protocol-header", "java.lang.String", null, "Header that holds the incoming protocol, usually named \"X-Forwarded-Proto\".\n Configured as a RemoteIpValve only if remoteIpHeader is also set.");
data("server.tomcat.remote-ip-header", "java.lang.String", null, "Name of the http header from which the remote ip is extracted. Configured as a\n RemoteIpValve only if remoteIpHeader is also set.");
data("server.tomcat.uri-encoding", "java.lang.String", null, "Character encoding to use to decode the URI.");
data("server.undertow.buffer-size", "java.lang.Integer", null, "Size of each buffer in bytes.");
data("server.undertow.buffers-per-region", "java.lang.Integer", null, "Number of buffer per region.");
data("server.undertow.direct-buffers", "java.lang.Boolean", null, null);
data("server.undertow.io-threads", "java.lang.Integer", null, "Number of I/O threads to create for the worker.");
data("server.undertow.worker-threads", "java.lang.Integer", null, "Number of worker threads.");
data("spring.activemq.broker-url", "java.lang.String", null, "URL of the ActiveMQ broker. Auto-generated by default.");
data("spring.activemq.in-memory", "java.lang.Boolean", "true", "Specify if the default broker URL should be in memory. Ignored if an explicit\n broker has been specified.");
data("spring.activemq.password", "java.lang.String", null, "Login password of the broker.");
data("spring.activemq.pooled", "java.lang.Boolean", "false", "Specify if a PooledConnectionFactory should be created instead of a regular\n ConnectionFactory.");
data("spring.activemq.user", "java.lang.String", null, "Login user of the broker.");
data("spring.aop.auto", "java.lang.Boolean", "true", "Add @EnableAspectJAutoProxy.");
data("spring.aop.proxy-target-class", "java.lang.Boolean", "false", "Whether subclass-based (CGLIB) proxies are to be created (true) as opposed to standard Java interface-based proxies (false).");
data("spring.application.index", "java.lang.Integer", null, "Application index.");
data("spring.application.name", "java.lang.String", null, "Application name.");
data("spring.batch.initializer.enabled", "java.lang.Boolean", "true", "Create the required batch tables on startup if necessary.");
data("spring.batch.job.enabled", "java.lang.Boolean", "true", "Execute all Spring Batch jobs in the context on startup.");
data("spring.batch.job.names", "java.lang.String", "", "Comma-separated list of job names to execute on startup. By default, all Jobs\n found in the context are executed.");
data("spring.batch.schema", "java.lang.String", "classpath:org/springframework/batch/core/schema-@@platform@@.sql", "Path to the SQL file to use to initialize the database schema.");
data("spring.config.location", "java.lang.String", null, "Config file locations.");
data("spring.config.name", "java.lang.String", "application", "Config file name.");
data("spring.dao.exceptiontranslation.enabled", "java.lang.Boolean", "true", "Enable the PersistenceExceptionTranslationPostProcessor.");
data("spring.data.elasticsearch.cluster-name", "java.lang.String", "elasticsearch", "Elasticsearch cluster name.");
data("spring.data.elasticsearch.cluster-nodes", "java.lang.String", null, "Comma-separated list of cluster node addresses. If not specified, starts a client\n node.");
data("spring.data.elasticsearch.repositories.enabled", "java.lang.Boolean", "true", "Enable Elasticsearch repositories.");
data("spring.data.jpa.repositories.enabled", "java.lang.Boolean", "true", "Enable JPA repositories.");
data("spring.data.mongodb.authentication-database", "java.lang.String", null, "Authentication database name.");
data("spring.data.mongodb.database", "java.lang.String", null, "Database name.");
data("spring.data.mongodb.grid-fs-database", "java.lang.String", null, "GridFS database name.");
data("spring.data.mongodb.host", "java.lang.String", null, "Mongo server host.");
data("spring.data.mongodb.password", "char[]", null, "Login password of the mongo server.");
data("spring.data.mongodb.port", "java.lang.Integer", null, "Mongo server port.");
data("spring.data.mongodb.repositories.enabled", "java.lang.Boolean", "true", "Enable Mongo repositories.");
data("spring.data.mongodb.uri", "java.lang.String", "mongodb://localhost/test", "Mmongo database URI. When set, host and port are ignored.");
data("spring.data.mongodb.username", "java.lang.String", null, "Login user of the mongo server.");
data("spring.data.rest.base-uri", "java.net.URI", null, null);
data("spring.data.rest.default-page-size", "java.lang.Integer", null, null);
data("spring.data.rest.limit-param-name", "java.lang.String", null, null);
data("spring.data.rest.max-page-size", "java.lang.Integer", null, null);
data("spring.data.rest.page-param-name", "java.lang.String", null, null);
data("spring.data.rest.return-body-on-create", "java.lang.Boolean", null, null);
data("spring.data.rest.return-body-on-update", "java.lang.Boolean", null, null);
data("spring.data.rest.sort-param-name", "java.lang.String", null, null);
data("spring.data.solr.host", "java.lang.String", "http://127.0.0.1:8983/solr", "Solr host. Ignored if \"zk-host\" is set.");
data("spring.data.solr.repositories.enabled", "java.lang.Boolean", "true", "Enable Solr repositories.");
data("spring.data.solr.zk-host", "java.lang.String", null, "ZooKeeper host address in the form HOST:PORT.");
data("spring.datasource.abandon-when-percentage-full", "java.lang.Integer", null, null);
data("spring.datasource.access-to-underlying-connection-allowed", "java.lang.Boolean", null, null);
data("spring.datasource.alternate-username-allowed", "java.lang.Boolean", null, null);
data("spring.datasource.auto-commit", "java.lang.Boolean", null, null);
data("spring.datasource.catalog", "java.lang.String", null, null);
data("spring.datasource.commit-on-return", "java.lang.Boolean", null, null);
data("spring.datasource.connection-customizer-class-name", "java.lang.String", null, null);
data("spring.datasource.connection-init-sql", "java.lang.String", null, null);
data("spring.datasource.connection-init-sqls", "java.util.Collection", null, null);
data("spring.datasource.connection-properties", "java.lang.String", null, null);
data("spring.datasource.connection-test-query", "java.lang.String", null, null);
data("spring.datasource.connection-timeout", "java.lang.Long", null, null);
data("spring.datasource.continue-on-error", "java.lang.Boolean", "false", "Do not stop if an error occurs while initializing the database.");
data("spring.datasource.data", "java.lang.String", null, "Data (DML) script resource reference.");
data("spring.datasource.data-source-class-name", "java.lang.String", null, null);
data("spring.datasource.data-source", "java.lang.Object", null, null);
data("spring.datasource.data-source-j-n-d-i", "java.lang.String", null, null);
data("spring.datasource.data-source-properties", "java.util.Properties", null, null);
data("spring.datasource.db-properties", "java.util.Properties", null, null);
data("spring.datasource.default-auto-commit", "java.lang.Boolean", null, null);
data("spring.datasource.default-catalog", "java.lang.String", null, null);
data("spring.datasource.default-read-only", "java.lang.Boolean", null, null);
data("spring.datasource.default-transaction-isolation", "java.lang.Integer", null, null);
data("spring.datasource.driver-class-name", "java.lang.String", null, "Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.");
data("spring.datasource.fair-queue", "java.lang.Boolean", null, null);
data("spring.datasource.idle-timeout", "java.lang.Long", null, null);
data("spring.datasource.ignore-exception-on-pre-load", "java.lang.Boolean", null, null);
data("spring.datasource.initialization-fail-fast", "java.lang.Boolean", null, null);
data("spring.datasource.initialize", "java.lang.Boolean", "true", "Populate the database using 'data.sql'.");
data("spring.datasource.initial-size", "java.lang.Integer", null, null);
data("spring.datasource.init-s-q-l", "java.lang.String", null, null);
data("spring.datasource.isolate-internal-queries", "java.lang.Boolean", null, null);
data("spring.datasource.jdbc4-connection-test", "java.lang.Boolean", null, null);
data("spring.datasource.jdbc-interceptors", "java.lang.String", null, null);
data("spring.datasource.jdbc-url", "java.lang.String", null, null);
data("spring.datasource.jmx-enabled", "java.lang.Boolean", "false", "Enable JMX support (if provided by the underlying pool).");
data("spring.datasource.jndi-name", "java.lang.String", null, "JNDI location of the datasource. Class, url, username & password are ignored when\n set.");
data("spring.datasource.leak-detection-threshold", "java.lang.Long", null, null);
data("spring.datasource.log-abandoned", "java.lang.Boolean", null, null);
data("spring.datasource.login-timeout", "java.lang.Integer", null, null);
data("spring.datasource.log-validation-errors", "java.lang.Boolean", null, null);
data("spring.datasource.max-active", "java.lang.Integer", null, null);
data("spring.datasource.max-age", "java.lang.Long", null, null);
data("spring.datasource.max-idle", "java.lang.Integer", null, null);
data("spring.datasource.maximum-pool-size", "java.lang.Integer", null, null);
data("spring.datasource.max-lifetime", "java.lang.Long", null, null);
data("spring.datasource.max-open-prepared-statements", "java.lang.Integer", null, null);
data("spring.datasource.max-wait", "java.lang.Integer", null, null);
data("spring.datasource.metric-registry", "java.lang.Object", null, null);
data("spring.datasource.min-evictable-idle-time-millis", "java.lang.Integer", null, null);
data("spring.datasource.min-idle", "java.lang.Integer", null, null);
data("spring.datasource.minimum-idle", "java.lang.Integer", null, null);
data("spring.datasource.name", "java.lang.String", null, null);
data("spring.datasource.num-tests-per-eviction-run", "java.lang.Integer", null, null);
data("spring.datasource.password", "java.lang.String", null, "Login password of the database.");
data("spring.datasource.platform", "java.lang.String", "all", "Platform to use in the schema resource (schema-${platform}.sql).");
data("spring.datasource.pool-name", "java.lang.String", null, null);
data("spring.datasource.pool-prepared-statements", "java.lang.Boolean", null, null);
data("spring.datasource.propagate-interrupt-state", "java.lang.Boolean", null, null);
data("spring.datasource.read-only", "java.lang.Boolean", null, null);
data("spring.datasource.register-mbeans", "java.lang.Boolean", null, null);
data("spring.datasource.remove-abandoned", "java.lang.Boolean", null, null);
data("spring.datasource.remove-abandoned-timeout", "java.lang.Integer", null, null);
data("spring.datasource.rollback-on-return", "java.lang.Boolean", null, null);
data("spring.datasource.schema", "java.lang.String", null, "Schema (DDL) script resource reference.");
data("spring.datasource.separator", "java.lang.String", ";", "Statement separator in SQL initialization scripts.");
data("spring.datasource.sql-script-encoding", "java.lang.String", null, "SQL scripts encoding.");
data("spring.datasource.suspect-timeout", "java.lang.Integer", null, null);
data("spring.datasource.test-on-borrow", "java.lang.Boolean", null, null);
data("spring.datasource.test-on-connect", "java.lang.Boolean", null, null);
data("spring.datasource.test-on-return", "java.lang.Boolean", null, null);
data("spring.datasource.test-while-idle", "java.lang.Boolean", null, null);
data("spring.datasource.time-between-eviction-runs-millis", "java.lang.Integer", null, null);
data("spring.datasource.transaction-isolation", "java.lang.String", null, null);
data("spring.datasource.url", "java.lang.String", null, "JDBC url of the database.");
data("spring.datasource.use-disposable-connection-facade", "java.lang.Boolean", null, null);
data("spring.datasource.use-equals", "java.lang.Boolean", null, null);
data("spring.datasource.use-lock", "java.lang.Boolean", null, null);
data("spring.datasource.username", "java.lang.String", null, "Login user of the database.");
data("spring.datasource.validation-interval", "java.lang.Long", null, null);
data("spring.datasource.validation-query", "java.lang.String", null, null);
data("spring.datasource.validation-query-timeout", "java.lang.Integer", null, null);
data("spring.datasource.validator-class-name", "java.lang.String", null, null);
data("spring.datasource.xa.data-source-class-name", "java.lang.String", null, "XA datasource fully qualified name.");
data("spring.datasource.xa.properties", "java.util.Map<java.lang.String,java.lang.String>", null, "Properties to pass to the XA data source.");
data("spring.freemarker.allow-request-override", "java.lang.Boolean", null, "Set whether HttpServletRequest attributes are allowed to override (hide) controller\n generated model attributes of the same name.");
data("spring.freemarker.cache", "java.lang.Boolean", null, "Enable template caching.");
data("spring.freemarker.char-set", "java.lang.String", null, null);
data("spring.freemarker.charset", "java.lang.String", null, "Template encoding.");
data("spring.freemarker.check-template-location", "java.lang.Boolean", null, "Check that the templates location exists.");
data("spring.freemarker.content-type", "java.lang.String", null, "Content-Type value.");
data("spring.freemarker.enabled", "java.lang.Boolean", null, "Enable MVC view resolution for this technology.");
data("spring.freemarker.expose-request-attributes", "java.lang.Boolean", null, "Set whether all request attributes should be added to the model prior to merging\n with the template.");
data("spring.freemarker.expose-session-attributes", "java.lang.Boolean", null, "Set whether all HttpSession attributes should be added to the model prior to\n merging with the template.");
data("spring.freemarker.expose-spring-macro-helpers", "java.lang.Boolean", null, "Set whether to expose a RequestContext for use by Spring's macro library, under the\n name \"springMacroRequestContext\".");
data("spring.freemarker.prefix", "java.lang.String", null, "Prefix that gets prepended to view names when building a URL.");
data("spring.freemarker.request-context-attribute", "java.lang.String", null, "Name of the RequestContext attribute for all views.");
data("spring.freemarker.settings", "java.util.Map<java.lang.String,java.lang.String>", null, "Well-known FreeMarker keys which will be passed to FreeMarker's Configuration.");
data("spring.freemarker.suffix", "java.lang.String", null, "Suffix that gets appended to view names when building a URL.");
data("spring.freemarker.template-loader-path", "java.lang.String[]", new String[] {"snuzzle" ,"buggles"}, "Comma-separated list of template paths.");
data("spring.freemarker.view-names", "java.lang.String[]", null, "White list of view names that can be resolved.");
data("spring.groovy.template.cache", "java.lang.Boolean", null, "Enable template caching.");
data("spring.groovy.template.char-set", "java.lang.String", null, null);
data("spring.groovy.template.charset", "java.lang.String", null, "Template encoding.");
data("spring.groovy.template.check-template-location", "java.lang.Boolean", null, "Check that the templates location exists.");
data("spring.groovy.template.configuration.auto-escape", "java.lang.Boolean", null, null);
data("spring.groovy.template.configuration.auto-indent", "java.lang.Boolean", null, null);
data("spring.groovy.template.configuration.auto-indent-string", "java.lang.String", null, null);
data("spring.groovy.template.configuration.auto-new-line", "java.lang.Boolean", null, null);
data("spring.groovy.template.configuration.base-template-class", "java.lang.Class<? extends groovy.text.markup.BaseTemplate>", null, null);
data("spring.groovy.template.configuration.cache-templates", "java.lang.Boolean", null, null);
data("spring.groovy.template.configuration.declaration-encoding", "java.lang.String", null, null);
data("spring.groovy.template.configuration.expand-empty-elements", "java.lang.Boolean", null, null);
data("spring.groovy.template.configuration", "java.util.Map<java.lang.String,java.lang.Object>", null, "Configuration to pass to TemplateConfiguration.");
data("spring.groovy.template.configuration.locale", "java.util.Locale", null, null);
data("spring.groovy.template.configuration.new-line-string", "java.lang.String", null, null);
data("spring.groovy.template.configuration.resource-loader-path", "java.lang.String", null, null);
data("spring.groovy.template.configuration.use-double-quotes", "java.lang.Boolean", null, null);
data("spring.groovy.template.content-type", "java.lang.String", null, "Content-Type value.");
data("spring.groovy.template.enabled", "java.lang.Boolean", null, "Enable MVC view resolution for this technology.");
data("spring.groovy.template.prefix", "java.lang.String", "classpath:/templates/", "Prefix that gets prepended to view names when building a URL.");
data("spring.groovy.template.suffix", "java.lang.String", ".tpl", "Suffix that gets appended to view names when building a URL.");
data("spring.groovy.template.view-names", "java.lang.String[]", null, "White list of view names that can be resolved.");
data("spring.hornetq.embedded.cluster-password", "java.lang.String", null, "Cluster password. Randomly generated on startup by default");
data("spring.hornetq.embedded.data-directory", "java.lang.String", null, "Journal file directory. Not necessary if persistence is turned off.");
data("spring.hornetq.embedded.enabled", "java.lang.Boolean", "true", "Enable embedded mode if the HornetQ server APIs are available.");
data("spring.hornetq.embedded.persistent", "java.lang.Boolean", "false", "Enable persistent store.");
data("spring.hornetq.embedded.queues", "java.lang.String[]", "[Ljava.lang.Object;@2f5ce114", "Comma-separate list of queues to create on startup.");
data("spring.hornetq.embedded.server-id", "java.lang.Integer", "0", "Server id. By default, an auto-incremented counter is used.");
data("spring.hornetq.embedded.topics", "java.lang.String[]", "[Ljava.lang.Object;@6272137a", "Comma-separate list of topics to create on startup.");
data("spring.hornetq.host", "java.lang.String", "localhost", "HornetQ broker host.");
data("spring.hornetq.mode", "org.springframework.boot.autoconfigure.jms.hornetq.HornetQMode", null, "HornetQ deployment mode, auto-detected by default. Can be explicitly set to\n \"native\" or \"embedded\".");
data("spring.hornetq.port", "java.lang.Integer", "5445", "HornetQ broker port.");
data("spring.http.encoding.charset", "java.nio.charset.Charset", null, "Charset of HTTP requests and responses. Added to the \"Content-Type\" header if not\n set explicitly.");
data("spring.http.encoding.enabled", "java.lang.Boolean", "true", "Enable http encoding support.");
data("spring.http.encoding.force", "java.lang.Boolean", "true", "Force the encoding to the configured charset on HTTP requests and responses.");
data("spring.jackson.date-format", "java.lang.String", null, "Date format string (yyyy-MM-dd HH:mm:ss), or a fully-qualified date format class\n name.");
data("spring.jackson.deserialization", "java.util.Map<com.fasterxml.jackson.databind.DeserializationFeature,java.lang.Boolean>", null, "Jackson on/off features that affect the way Java objects are deserialized.");
data("spring.jackson.generator", "java.util.Map<com.fasterxml.jackson.core.JsonGenerator.Feature,java.lang.Boolean>", null, "Jackson on/off features for generators.");
data("spring.jackson.mapper", "java.util.Map<com.fasterxml.jackson.databind.MapperFeature,java.lang.Boolean>", null, "Jackson general purpose on/off features.");
data("spring.jackson.parser", "java.util.Map<com.fasterxml.jackson.core.JsonParser.Feature,java.lang.Boolean>", null, "Jackson on/off features for parsers.");
data("spring.jackson.property-naming-strategy", "java.lang.String", null, "One of the constants on Jackson's PropertyNamingStrategy\n (CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES). Can also be a fully-qualified class\n name of a PropertyNamingStrategy subclass.");
data("spring.jackson.serialization", "java.util.Map<com.fasterxml.jackson.databind.SerializationFeature,java.lang.Boolean>", null, "Jackson on/off features that affect the way Java objects are serialized.");
data("spring.jersey.filter.order", "java.lang.Integer", "0", "Jersey filter chain order.");
data("spring.jersey.init", "java.util.Map<java.lang.String,java.lang.String>", null, "Init parameters to pass to Jersey.");
data("spring.jersey.type", "org.springframework.boot.autoconfigure.jersey.JerseyProperties$Type", null, "Jersey integration type. Can be either \"servlet\" or \"filter\".");
data("spring.jms.jndi-name", "java.lang.String", null, "Connection factory JNDI name. When set, takes precedence to others connection\n factory auto-configurations.");
data("spring.jms.pub-sub-domain", "java.lang.Boolean", "false", "Specify if the default destination type is topic.");
data("spring.jmx.enabled", "java.lang.Boolean", "true", "Expose management beans to the JMX domain.");
data("spring.jpa.database", "org.springframework.orm.jpa.vendor.Database", null, "Target database to operate on, auto-detected by default. Can be alternatively set\n using the \"databasePlatform\" property.");
data("spring.jpa.database-platform", "java.lang.String", null, "Name of the target database to operate on, auto-detected by default. Can be\n alternatively set using the \"Database\" enum.");
data("spring.jpa.generate-ddl", "java.lang.Boolean", "false", "Initialize the schema on startup.");
data("spring.jpa.hibernate.ddl-auto", "java.lang.String", null, "DDL mode (\"none\", \"validate\", \"update\", \"create\", \"create-drop\"). This is\n actually a shortcut for the \"hibernate.hbm2ddl.auto\" property. Default to\n \"create-drop\" when using an embedded database, \"none\" otherwise.");
data("spring.jpa.hibernate.naming-strategy", "java.lang.Class<?>", null, "Naming strategy fully qualified name.");
data("spring.jpa.open-in-view", "java.lang.Boolean", "true", "Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.");
data("spring.jpa.properties", "java.util.Map<java.lang.String,java.lang.String>", null, "Additional native properties to set on the JPA provider.");
data("spring.jpa.show-sql", "java.lang.Boolean", "false", "Enable logging of SQL statements.");
data("spring.jta.allow-multiple-lrc", "java.lang.Boolean", null, null);
data("spring.jta.asynchronous2-pc", "java.lang.Boolean", null, null);
data("spring.jta.background-recovery-interval", "java.lang.Integer", null, null);
data("spring.jta.background-recovery-interval-seconds", "java.lang.Integer", null, null);
data("spring.jta.current-node-only-recovery", "java.lang.Boolean", null, null);
data("spring.jta.debug-zero-resource-transaction", "java.lang.Boolean", null, null);
data("spring.jta.default-transaction-timeout", "java.lang.Integer", null, null);
data("spring.jta.disable-jmx", "java.lang.Boolean", null, null);
data("spring.jta.enabled", "java.lang.Boolean", "true", "Enable JTA support.");
data("spring.jta.exception-analyzer", "java.lang.String", null, null);
data("spring.jta.filter-log-status", "java.lang.Boolean", null, null);
data("spring.jta.force-batching-enabled", "java.lang.Boolean", null, null);
data("spring.jta.forced-write-enabled", "java.lang.Boolean", null, null);
data("spring.jta.graceful-shutdown-interval", "java.lang.Integer", null, null);
data("spring.jta.jndi-transaction-synchronization-registry-name", "java.lang.String", null, null);
data("spring.jta.jndi-user-transaction-name", "java.lang.String", null, null);
data("spring.jta.journal", "java.lang.String", null, null);
data("spring.jta.log-dir", "java.lang.String", null, "Transaction logs directory.");
data("spring.jta.log-part1-filename", "java.lang.String", null, null);
data("spring.jta.log-part2-filename", "java.lang.String", null, null);
data("spring.jta.max-log-size-in-mb", "java.lang.Integer", null, null);
data("spring.jta.resource-configuration-filename", "java.lang.String", null, null);
data("spring.jta.server-id", "java.lang.String", null, null);
data("spring.jta.skip-corrupted-logs", "java.lang.Boolean", null, null);
data("spring.jta.transaction-manager-id", "java.lang.String", null, "Transaction manager unique identifier.");
data("spring.jta.warn-about-zero-resource-transaction", "java.lang.Boolean", null, null);
data("spring.mail.default-encoding", "java.lang.String", "UTF-8", "Default MimeMessage encoding.");
data("spring.mail.host", "java.lang.String", null, "SMTP server host.");
data("spring.mail.password", "java.lang.String", null, "Login password of the SMTP server.");
data("spring.mail.port", "java.lang.Integer", null, "SMTP server port.");
data("spring.mail.properties", "java.util.Map<java.lang.String,java.lang.String>", null, "Additional JavaMail session properties.");
data("spring.mail.username", "java.lang.String", null, "Login user of the SMTP server.");
data("spring.main.show-banner", "java.lang.Boolean", "true", "Display the banner when the application runs.");
data("spring.main.sources", "java.util.Set<java.lang.Object>", null, "Sources (class name, package name or XML resource location) used to create the ApplicationContext.");
data("spring.main.web-environment", "java.lang.Boolean", null, "Run the application in a web environment (auto-detected by default).");
data("spring.mandatory-file-encoding", "java.lang.String", null, "Expected character encoding the application must use.");
data("spring.messages.basename", "java.lang.String", "messages", "Comma-separated list of basenames, each following the ResourceBundle convention.\n Essentially a fully-qualified classpath location. If it doesn't contain a package\n qualifier (such as \"org.mypackage\"), it will be resolved from the classpath root.");
data("spring.messages.cache-seconds", "java.lang.Integer", "-1", "Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles\n are cached forever.");
data("spring.messages.encoding", "java.lang.String", "utf-8", "Message bundles encoding.");
data("spring.mobile.devicedelegatingviewresolver.enabled", "java.lang.Boolean", "false", "Enable device view resolver.");
data("spring.mobile.devicedelegatingviewresolver.mobile-prefix", "java.lang.String", "mobile/", "Prefix that gets prepended to view names for mobile devices.");
data("spring.mobile.devicedelegatingviewresolver.mobile-suffix", "java.lang.String", "", "Suffix that gets appended to view names for mobile devices.");
data("spring.mobile.devicedelegatingviewresolver.normal-prefix", "java.lang.String", "", "Prefix that gets prepended to view names for normal devices.");
data("spring.mobile.devicedelegatingviewresolver.normal-suffix", "java.lang.String", "", "Suffix that gets appended to view names for normal devices.");
data("spring.mobile.devicedelegatingviewresolver.tablet-prefix", "java.lang.String", "tablet/", "Prefix that gets prepended to view names for tablet devices.");
data("spring.mobile.devicedelegatingviewresolver.tablet-suffix", "java.lang.String", "", "Suffix that gets appended to view names for tablet devices.");
data("spring.mobile.sitepreference.enabled", "java.lang.Boolean", "true", "Enable SitePreferenceHandler.");
data("spring.mvc.date-format", "java.lang.String", null, "Date format to use (e.g. dd/MM/yyyy)");
data("spring.mvc.ignore-default-model-on-redirect", "java.lang.Boolean", "true", "If the the content of the \"default\" model should be ignored during redirect\n scenarios.");
data("spring.mvc.locale", "java.lang.String", null, "Locale to use.");
data("spring.mvc.message-codes-resolver-format", "org.springframework.validation.DefaultMessageCodesResolver$Format", null, "Formatting strategy for message codes (PREFIX_ERROR_CODE, POSTFIX_ERROR_CODE).");
data("spring.profiles.active", "java.lang.String", null, "Comma-separated list of active profiles. Can be overridden by a command line switch.");
data("spring.profiles.include", "java.lang.String", null, "Unconditionally activate the specified comma separated profiles.");
data("spring.rabbitmq.addresses", "java.lang.String", null, "Comma-separated list of addresses to which the client should connect to.");
data("spring.rabbitmq.dynamic", "java.lang.Boolean", "true", "Create an AmqpAdmin bean.");
data("spring.rabbitmq.host", "java.lang.String", "localhost", "RabbitMQ host.");
data("spring.rabbitmq.password", "java.lang.String", null, "Login to authenticate against the broker.");
data("spring.rabbitmq.port", "java.lang.Integer", "5672", "RabbitMQ port.");
data("spring.rabbitmq.username", "java.lang.String", null, "Login user to authenticate to the broker.");
data("spring.rabbitmq.virtual-host", "java.lang.String", null, "Virtual host to use when connecting to the broker.");
data("spring.redis.database", "java.lang.Integer", "0", "Database index used by the connection factory.");
data("spring.redis.host", "java.lang.String", "localhost", "Redis server host.");
data("spring.redis.password", "java.lang.String", null, "Login password of the redis server.");
data("spring.redis.pool.max-active", "java.lang.Integer", "8", "Max number of connections that can be allocated by the pool at a given time.\n Use a negative value for no limit.");
data("spring.redis.pool.max-idle", "java.lang.Integer", "8", "Max number of \"idle\" connections in the pool. Use a negative value to indicate\n an unlimited number of idle connections.");
data("spring.redis.pool.max-wait", "java.lang.Integer", "-1", "Maximum amount of time (in milliseconds) a connection allocation should block\n before throwing an exception when the pool is exhausted. Use a negative value\n to block indefinitely.");
data("spring.redis.pool.min-idle", "java.lang.Integer", "0", "Target for the minimum number of idle connections to maintain in the pool. This\n setting only has an effect if it is positive.");
data("spring.redis.port", "java.lang.Integer", "6379", "Redis server port.");
data("spring.redis.sentinel.master", "java.lang.String", null, "Name of Redis server.");
data("spring.redis.sentinel.nodes", "java.lang.String", null, "Comma-separated list of host:port pairs.");
data("spring.resources.add-mappings", "java.lang.Boolean", "true", "Enable default resource handling.");
data("spring.resources.cache-period", "java.lang.Integer", null, "Cache period for the resources served by the resource handler, in seconds.");
data("spring.social.auto-connection-views", "java.lang.Boolean", "false", "Enable the connection status view for supported providers.");
data("spring.social.facebook.app-id", "java.lang.String", null, "Application id.");
data("spring.social.facebook.app-secret", "java.lang.String", null, "Application secret.");
data("spring.social.linkedin.app-id", "java.lang.String", null, "Application id.");
data("spring.social.linkedin.app-secret", "java.lang.String", null, "Application secret.");
data("spring.social.twitter.app-id", "java.lang.String", null, "Application id.");
data("spring.social.twitter.app-secret", "java.lang.String", null, "Application secret.");
data("spring.thymeleaf.cache", "java.lang.Boolean", "true", "Enable template caching.");
data("spring.thymeleaf.check-template-location", "java.lang.Boolean", "true", "Check that the templates location exists.");
data("spring.thymeleaf.content-type", "java.lang.String", "text/html", "Content-Type value.");
data("spring.thymeleaf.enabled", "java.lang.Boolean", "true", "Enable MVC Thymeleaf view resolution.");
data("spring.thymeleaf.encoding", "java.lang.String", "UTF-8", "Template encoding.");
data("spring.thymeleaf.excluded-view-names", "java.lang.String[]", null, "Comma-separated list of view names that should be excluded from resolution.");
data("spring.thymeleaf.mode", "java.lang.String", "HTML5", "Template mode to be applied to templates. See also StandardTemplateModeHandlers.");
data("spring.thymeleaf.prefix", "java.lang.String", "classpath:/templates/", "Prefix that gets prepended to view names when building a URL.");
data("spring.thymeleaf.suffix", "java.lang.String", ".html", "Suffix that gets appended to view names when building a URL.");
data("spring.thymeleaf.view-names", "java.lang.String[]", null, "Comma-separated list of view names that can be resolved.");
data("spring.velocity.allow-request-override", "java.lang.Boolean", null, "Set whether HttpServletRequest attributes are allowed to override (hide) controller\n generated model attributes of the same name.");
data("spring.velocity.cache", "java.lang.Boolean", null, "Enable template caching.");
data("spring.velocity.char-set", "java.lang.String", null, null);
data("spring.velocity.charset", "java.lang.String", null, "Template encoding.");
data("spring.velocity.check-template-location", "java.lang.Boolean", null, "Check that the templates location exists.");
data("spring.velocity.content-type", "java.lang.String", null, "Content-Type value.");
data("spring.velocity.date-tool-attribute", "java.lang.String", null, "Name of the DateTool helper object to expose in the Velocity context of the view.");
data("spring.velocity.enabled", "java.lang.Boolean", null, "Enable MVC view resolution for this technology.");
data("spring.velocity.expose-request-attributes", "java.lang.Boolean", null, "Set whether all request attributes should be added to the model prior to merging\n with the template.");
data("spring.velocity.expose-session-attributes", "java.lang.Boolean", null, "Set whether all HttpSession attributes should be added to the model prior to\n merging with the template.");
data("spring.velocity.expose-spring-macro-helpers", "java.lang.Boolean", null, "Set whether to expose a RequestContext for use by Spring's macro library, under the\n name \"springMacroRequestContext\".");
data("spring.velocity.number-tool-attribute", "java.lang.String", null, "Name of the NumberTool helper object to expose in the Velocity context of the view.");
data("spring.velocity.prefer-file-system-access", "java.lang.Boolean", "true", "Prefer file system access for template loading. File system access enables hot\n detection of template changes.");
data("spring.velocity.prefix", "java.lang.String", null, "Prefix that gets prepended to view names when building a URL.");
data("spring.velocity.properties", "java.util.Map<java.lang.String,java.lang.String>", null, "Additional velocity properties.");
data("spring.velocity.request-context-attribute", "java.lang.String", null, "Name of the RequestContext attribute for all views.");
data("spring.velocity.resource-loader-path", "java.lang.String", "classpath:/templates/", "Template path.");
data("spring.velocity.suffix", "java.lang.String", null, "Suffix that gets appended to view names when building a URL.");
data("spring.velocity.toolbox-config-location", "java.lang.String", null, "Velocity Toolbox config location, for example \"/WEB-INF/toolbox.xml\". Automatically\n loads a Velocity Tools toolbox definition file and expose all defined tools in the\n specified scopes.");
data("spring.velocity.view-names", "java.lang.String[]", null, "White list of view names that can be resolved.");
data("spring.view.prefix", "java.lang.String", null, "Spring MVC view prefix.");
data("spring.view.suffix", "java.lang.String", null, "Spring MVC view suffix.");
}
public boolean isEmpty() {
return datas == null || datas.isEmpty();
}
public SpringPropertyIndexProvider getIndexProvider() {
return indexProvider;
}
}

View File

@@ -0,0 +1,24 @@
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/

View File

@@ -0,0 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip

View File

@@ -0,0 +1,233 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
#
# Look for the Apple JDKs first to preserve the existing behaviour, and then look
# for the new JDKs provided by Oracle.
#
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
#
# Apple JDKs
#
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
fi
if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
#
# Apple JDKs
#
export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
fi
if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
#
# Oracle JDKs
#
export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
fi
if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
#
# Apple JDKs
#
export JAVA_HOME=`/usr/libexec/java_home`
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Migwn, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
local basedir=$(pwd)
local wdir=$(pwd)
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
wdir=$(cd "$wdir/.."; pwd)
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} "$@"

View File

@@ -0,0 +1,145 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
set MAVEN_CMD_LINE_ARGS=%*
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar""
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>test-scope-annotation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test-scope-annotation</name>
<description>Test projects for spring boot java language server - scope annotations</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,12 @@
package org.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestAnnotationsApplication {
public static void main(String[] args) {
SpringApplication.run(TestAnnotationsApplication.class, args);
}
}

View File

@@ -0,0 +1,14 @@
package org.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
@Scope("onClass")
public class TestScopeCompletion {
@Bean
@Scope("onMethod")
public Object myBean() {
return null;
}
}

View File

@@ -0,0 +1,17 @@
package org.test;
import org.springframework.beans.factory.annotation.Value;
public class TestValueCompletion {
@Value("onField")
private String value1;
@Value("onMethod")
public void method1() {
}
public void method2(@Value("onParameter") String parameter1) {
}
}

View File

@@ -0,0 +1,4 @@
something:
else: true
appl1:
prop: test

View File

@@ -0,0 +1,4 @@
something:
else: true
appl1:
prop: test

View File

@@ -0,0 +1,5 @@
test.property=Hey there
server.port=8080
another.property=moretests

View File

@@ -0,0 +1,4 @@
server:
port: 8080
test:
property: mytestproperty