Split vscode-boot-java to separate out language-server
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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++);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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/
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
|
||||
233
headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotations/mvnw
vendored
Executable file
233
headless-services/boot-java-language-server/src/test/resources/test-projects/test-annotations/mvnw
vendored
Executable 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} "$@"
|
||||
@@ -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%
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,4 @@
|
||||
something:
|
||||
else: true
|
||||
appl1:
|
||||
prop: test
|
||||
@@ -0,0 +1,4 @@
|
||||
something:
|
||||
else: true
|
||||
appl1:
|
||||
prop: test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,2 @@
|
||||
something.else=true
|
||||
appl1.prop=test
|
||||
@@ -0,0 +1,5 @@
|
||||
test.property=Hey there
|
||||
|
||||
server.port=8080
|
||||
|
||||
another.property=moretests
|
||||
@@ -0,0 +1,4 @@
|
||||
server:
|
||||
port: 8080
|
||||
test:
|
||||
property: mytestproperty
|
||||
Reference in New Issue
Block a user