Application yaml now verifies simple
property names
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -10,14 +10,19 @@
|
||||
<artifactId>application-properties-metadata</artifactId>
|
||||
<description>Builds metadata for boot application properties based on project's classpath contents</description>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>project-repo</id>
|
||||
<url>file://${project.basedir}/repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Local modified JSON lib packaged to support order in maps -->
|
||||
<dependency>
|
||||
<groupId>libs</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<groupId>org.springframework.ide.eclipse</groupId>
|
||||
<artifactId>org.json</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/lib/org.springframework.ide.eclipse.org.json-20140107-repackaged.jar</systemPath>
|
||||
</dependency>
|
||||
<!-- Guava collections -->
|
||||
<dependency>
|
||||
@@ -44,6 +49,16 @@
|
||||
<artifactId>commons-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-yaml</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-java</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-language-server</artifactId>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.ide.eclipse</groupId>
|
||||
<artifactId>org.json</artifactId>
|
||||
<version>1.0</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<groupId>org.springframework.ide.eclipse</groupId>
|
||||
<artifactId>org.json</artifactId>
|
||||
<versioning>
|
||||
<release>1.0</release>
|
||||
<versions>
|
||||
<version>1.0</version>
|
||||
</versions>
|
||||
<lastUpdated>20161019231202</lastUpdated>
|
||||
</versioning>
|
||||
</metadata>
|
||||
@@ -0,0 +1,133 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 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.properties.metadata;
|
||||
|
||||
import static org.springframework.ide.vscode.util.StringUtil.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.boot.properties.util.FuzzyMap;
|
||||
import org.springframework.ide.vscode.boot.properties.util.FuzzyMap.Match;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
|
||||
/**
|
||||
* An index navigator allows selecting subset of a property index as if
|
||||
* navigating the index by selecting on a property
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class IndexNavigator {
|
||||
|
||||
//Possible opitmization: we could cache prefix match candidate and extended match candidate
|
||||
// since it is assumed that the index is immutable for the lifetime of
|
||||
// the index navigator.
|
||||
|
||||
private static final char NAV_CHAR = '.';
|
||||
|
||||
/**
|
||||
* Property access in this navigator are interpreted relative
|
||||
* to this prefix
|
||||
*/
|
||||
private String prefix = null;
|
||||
private FuzzyMap<PropertyInfo> index;
|
||||
|
||||
private IndexNavigator(FuzzyMap<PropertyInfo> index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
private IndexNavigator(FuzzyMap<PropertyInfo> index, String prefix) {
|
||||
this.index = index;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public static IndexNavigator with(FuzzyMap<PropertyInfo> index) {
|
||||
return new IndexNavigator(index);
|
||||
}
|
||||
|
||||
public IndexNavigator selectSubProperty(String name) {
|
||||
return new IndexNavigator(index, join(prefix, name));
|
||||
}
|
||||
|
||||
protected String join(String prefix, String postfix) {
|
||||
if (!hasText(prefix)) {
|
||||
return postfix;
|
||||
} else {
|
||||
return prefix + NAV_CHAR + postfix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return property info that is an exact match with the current prefix or
|
||||
* null if there's no exact match
|
||||
*/
|
||||
public PropertyInfo getExactMatch() {
|
||||
if (prefix!=null) {
|
||||
PropertyInfo candidate = index.findLongestCommonPrefixEntry(prefix);
|
||||
if (candidate.getId().equals(prefix)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a property that has the current prefix as a 'true' prefix. A true prefix
|
||||
* is a String that has the current prefix as a prefix and continues onward with
|
||||
* a navigation operation.
|
||||
*/
|
||||
public PropertyInfo getExtensionCandidate() {
|
||||
//If current prefix is null then all entries in the index are candidates since
|
||||
// the index is at the 'root' of the tree and we don't need a '.' to navigate
|
||||
String extendedPrefix = prefix==null?"":prefix + NAV_CHAR;
|
||||
PropertyInfo candidate = index.findLongestCommonPrefixEntry(extendedPrefix);
|
||||
if (candidate.getId().startsWith(extendedPrefix)) {
|
||||
return candidate;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public List<Match<PropertyInfo>> findMatching(String query) {
|
||||
if (!StringUtil.hasText(prefix)) {
|
||||
return index.find(query);
|
||||
} else {
|
||||
String dottedPrefix = prefix +".";
|
||||
List<Match<PropertyInfo>> candidates = index.find(dottedPrefix + query);
|
||||
if (!candidates.isEmpty()) {
|
||||
//TODO: we can do better than this using treemap to narrow based on
|
||||
// prefix
|
||||
List<Match<PropertyInfo>> matches = new ArrayList<Match<PropertyInfo>>(candidates.size());
|
||||
for (Match<PropertyInfo> match : candidates) {
|
||||
if (match.data.getId().startsWith(dottedPrefix)){
|
||||
matches.add(match);
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IndexNavigator("+prefix+")";
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return getExactMatch()==null && getExtensionCandidate()==null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,12 +10,11 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.properties.metadata;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.boot.properties.util.FuzzyMap;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
|
||||
public abstract class SpringPropertyIndexProvider {
|
||||
|
||||
public abstract FuzzyMap<PropertyInfo> getIndex(IDocument doc);
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SpringPropertyIndexProvider {
|
||||
FuzzyMap<PropertyInfo> getIndex(IDocument doc);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,18 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.properties.metadata;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.boot.configurationmetadata.ValueProvider;
|
||||
import org.springframework.ide.vscode.boot.properties.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.boot.properties.metadata.types.StsValueHint;
|
||||
import org.springframework.ide.vscode.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.util.CollectionUtil;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* An instance of this class serves as a 'registry' that associates known
|
||||
@@ -50,14 +55,14 @@ public class ValueProviderRegistry {
|
||||
private Map<String, Function<Map<String, Object>, ValueProviderStrategy>> registry = new HashMap<>();
|
||||
|
||||
public interface ValueProviderStrategy {
|
||||
// Flux<StsValueHint> getValues(IJavaProject javaProject, String query);
|
||||
//
|
||||
// default Collection<StsValueHint> getValuesNow(IJavaProject javaProject, String query) {
|
||||
// return this.getValues(javaProject, query)
|
||||
// .take(CachingValueProvider.TIMEOUT)
|
||||
// .collectList()
|
||||
// .block();
|
||||
// }
|
||||
Flux<StsValueHint> getValues(IJavaProject javaProject, String query);
|
||||
|
||||
default Collection<StsValueHint> getValuesNow(IJavaProject javaProject, String query) {
|
||||
return this.getValues(javaProject, query)
|
||||
.take(CachingValueProvider.TIMEOUT)
|
||||
.collectList()
|
||||
.block();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
import static org.springframework.ide.vscode.boot.properties.util.DeprecationUtil.*;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.boot.configurationmetadata.Deprecation;
|
||||
import org.springframework.boot.configurationmetadata.ValueHint;
|
||||
import org.springframework.ide.vscode.boot.properties.util.DeprecationUtil;
|
||||
import org.springframework.ide.vscode.java.IJavaElement;
|
||||
import org.springframework.ide.vscode.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.java.IType;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
import org.springframework.ide.vscode.util.Log;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Sts version of {@link ValueHint} contains similar data, but accomoates
|
||||
* a html snippet to be computed lazyly for the description.
|
||||
* <p>
|
||||
* This is meant to support using data pulled from JavaDoc in enums as description.
|
||||
* This data is a html snippet, whereas the data derived from spring-boot metadata is
|
||||
* just plain text.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class StsValueHint {
|
||||
|
||||
private static final HtmlSnippet EMPTY_DESCRIPTION = HtmlSnippet.italic("No description");
|
||||
|
||||
private static final Provider<HtmlSnippet> EMPTY_DESCRIPTION_PROVIDER = () -> EMPTY_DESCRIPTION;
|
||||
|
||||
private final String value;
|
||||
private final Provider<HtmlSnippet> description;
|
||||
private final Deprecation deprecation;
|
||||
|
||||
/**
|
||||
* Create a hint with a textual description.
|
||||
* <p>
|
||||
* This constructor is private. Use one of the provided
|
||||
* static 'create' methods instead.
|
||||
*/
|
||||
private StsValueHint(String value, Provider<HtmlSnippet> description, Deprecation deprecation) {
|
||||
this.value = value==null?"null":value.toString();
|
||||
Assert.isLegal(!this.value.startsWith("StsValueHint"));
|
||||
this.description = description;
|
||||
this.deprecation = deprecation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a hint out of an IJavaElement.
|
||||
*/
|
||||
public static StsValueHint create(String value, IJavaElement javaElement) {
|
||||
return new StsValueHint(value, javaDocSnippet(javaElement), DeprecationUtil.extract(javaElement)) {
|
||||
@Override
|
||||
public IJavaElement getJavaElement() {
|
||||
return javaElement;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static StsValueHint create(String value) {
|
||||
return new StsValueHint(value, EMPTY_DESCRIPTION_PROVIDER, null);
|
||||
}
|
||||
|
||||
public static StsValueHint create(ValueHint hint) {
|
||||
return new StsValueHint(""+hint.getValue(), textSnippet(hint.getDescription()), null);
|
||||
}
|
||||
|
||||
public static StsValueHint className(String fqName, TypeUtil typeUtil) {
|
||||
try {
|
||||
IJavaProject jp = typeUtil.getJavaProject();
|
||||
if (jp!=null) {
|
||||
IType type = jp.findType(fqName);
|
||||
if (type!=null) {
|
||||
return create(type);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static StsValueHint create(IType klass) {
|
||||
return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(klass), DeprecationUtil.extract(klass)) {
|
||||
@Override
|
||||
public IJavaElement getJavaElement() {
|
||||
return klass;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a html snippet from a text snippet.
|
||||
*/
|
||||
private static Provider<HtmlSnippet> textSnippet(String description) {
|
||||
if (StringUtil.hasText(description)) {
|
||||
return () -> HtmlSnippet.text(description);
|
||||
}
|
||||
return EMPTY_DESCRIPTION_PROVIDER;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public HtmlSnippet getDescription() {
|
||||
return description.get();
|
||||
}
|
||||
public Provider<HtmlSnippet> getDescriptionProvider() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static Provider<HtmlSnippet> javaDocSnippet(IJavaElement je) {
|
||||
return () -> {
|
||||
try {
|
||||
HtmlSnippet jdoc = je.getJavaDoc();
|
||||
if (jdoc!=null) {
|
||||
return jdoc;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return EMPTY_DESCRIPTION;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StsValueHint("+value+")";
|
||||
}
|
||||
|
||||
public Deprecation getDeprecation() {
|
||||
return deprecation;
|
||||
}
|
||||
|
||||
public IJavaElement getJavaElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public StsValueHint prefixWith(String prefix) {
|
||||
StsValueHint it = this;
|
||||
return new StsValueHint(prefix+getValue(), description, deprecation) {
|
||||
@Override
|
||||
public IJavaElement getJavaElement() {
|
||||
return it.getJavaElement();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 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.properties.metadata.types;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ide.vscode.java.IType;
|
||||
import org.springframework.ide.vscode.util.ArrayUtils;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.Log;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
import org.springframework.ide.vscode.yaml.schema.YType;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class Type implements YType {
|
||||
|
||||
private final String erasure;
|
||||
private final Type[] params;
|
||||
|
||||
public Type(String erasure, Type[] params) {
|
||||
this.erasure = erasure;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
|
||||
public boolean isGeneric() {
|
||||
return params!=null;
|
||||
}
|
||||
|
||||
public String getErasure() {
|
||||
return erasure;
|
||||
}
|
||||
public Type[] getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
toString(buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void toString(StringBuilder buf) {
|
||||
buf.append(getErasure());
|
||||
if (isGeneric()) {
|
||||
buf.append("<");
|
||||
boolean first = true;
|
||||
for (Type param : getParams()) {
|
||||
if (!first) {
|
||||
buf.append(",");
|
||||
}
|
||||
param.toString(buf);
|
||||
first = false;
|
||||
}
|
||||
buf.append(">");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to convert given typeSignature to a corresponding Type object.
|
||||
* <p>
|
||||
* Not all valid typeSig have a representation as a Type object. This may
|
||||
* return null if no corresponding representation can be constructed.
|
||||
*/
|
||||
public static Type fromSignature(String typeSig, IType context) {
|
||||
//TODO: does this work correctly with nested types (i.e like Map$Entry)
|
||||
Type type = TYPE_FROM_SIG.get(typeSig);
|
||||
if (type!=null) {
|
||||
return type;
|
||||
}
|
||||
int kind = Signature.getTypeSignatureKind(typeSig);
|
||||
//Essentially, Type object only able to represent class types with with generic parameters
|
||||
// as long as these generic parameters are fully concrete (i.e. do not contain unbound type
|
||||
// variables. For now only support the simplest case (no generics) and bail out returning null if we
|
||||
// see something we don't understand.
|
||||
if (kind==Signature.CLASS_TYPE_SIGNATURE) {
|
||||
boolean shouldResolve = typeSig.charAt(0)==Signature.C_UNRESOLVED;
|
||||
String erasure = Signature.getTypeErasure(typeSig);
|
||||
String pkg = Signature.getSignatureQualifier(erasure);
|
||||
String nam = Signature.getSignatureSimpleName(erasure);
|
||||
String[] params = Signature.getTypeParameters(typeSig);
|
||||
String[] args = Signature.getTypeArguments(typeSig);
|
||||
if (shouldResolve) {
|
||||
erasure = tryToResolve(qualifiedName(pkg, nam), context);
|
||||
} else {
|
||||
erasure = qualifiedName(pkg, nam);
|
||||
}
|
||||
if (ArrayUtils.hasElements(params)) {
|
||||
//TODO: handle this case
|
||||
return null;
|
||||
} else if (ArrayUtils.hasElements(args)) {
|
||||
Type[] argTypes = new Type[args.length];
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
argTypes[i] = fromSignature(args[i], context);
|
||||
}
|
||||
return new Type(erasure, argTypes);
|
||||
} else {
|
||||
return new Type(erasure, null);
|
||||
}
|
||||
} else if (kind==Signature.ARRAY_TYPE_SIGNATURE) {
|
||||
Type elementType = fromSignature(Signature.getElementType(typeSig), context);
|
||||
if (elementType!=null) {
|
||||
int arrayCount = Signature.getArrayCount(typeSig);
|
||||
return elementType.asArray(arrayCount);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Type asArray(int arrayCount) {
|
||||
Assert.isLegal(arrayCount>0);
|
||||
StringBuilder arrayErasure = new StringBuilder(erasure);
|
||||
for (int i = 0; i < arrayCount; i++) {
|
||||
arrayErasure.append("[]");
|
||||
}
|
||||
return new Type(arrayErasure.toString(), params);
|
||||
}
|
||||
|
||||
private static String qualifiedName(String pkg, String nam) {
|
||||
if (StringUtil.hasText(pkg)) {
|
||||
return pkg + "." + nam;
|
||||
} else {
|
||||
return nam;
|
||||
}
|
||||
}
|
||||
|
||||
private static String tryToResolve(String typeName, IType context) {
|
||||
try {
|
||||
String[][] resolved = context.resolveType(typeName);
|
||||
if (ArrayUtils.hasElements(resolved)) {
|
||||
String pkg = resolved[0][0];
|
||||
String nam = resolved[0][1];
|
||||
if (StringUtil.hasText(pkg)) {
|
||||
return pkg+"."+nam;
|
||||
} else {
|
||||
//No . in front of default package
|
||||
return nam;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Map of some known / common type signatures and their corresponding 'Type' representation.
|
||||
* Note that springboot metadata 'normalizes' all primitive types to their corresponding box
|
||||
* types. So we do the same here.
|
||||
*/
|
||||
private static final Map<String,Type> TYPE_FROM_SIG = new HashMap<String, Type>();
|
||||
static {
|
||||
sig2type("B", Byte.class);
|
||||
sig2type("C", Character.class);
|
||||
sig2type("D", Double.class);
|
||||
sig2type("F", Float.class);
|
||||
sig2type("I", Integer.class);
|
||||
sig2type("J", Long.class);
|
||||
sig2type("S", Short.class);
|
||||
sig2type("V", Void.class);
|
||||
sig2type("Z", Boolean.class);
|
||||
}
|
||||
private static void sig2type(String sig, Class<?> cls) {
|
||||
TYPE_FROM_SIG.put(sig, TypeParser.parse(cls.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((erasure == null) ? 0 : erasure.hashCode());
|
||||
result = prime * result + Arrays.hashCode(params);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Type other = (Type) obj;
|
||||
if (erasure == null) {
|
||||
if (other.erasure != null)
|
||||
return false;
|
||||
} else if (!erasure.equals(other.erasure))
|
||||
return false;
|
||||
if (!Arrays.equals(params, other.params))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
|
||||
/**
|
||||
* Converts types in notation used by spring properties metadata into a 'Structured' form
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class TypeParser {
|
||||
|
||||
private static final String DELIM = "<>,";
|
||||
|
||||
/**
|
||||
* Wrapper around StringTokenizer that manages a single lookahead token.
|
||||
* So it can implement 'peekToken()' method.
|
||||
*/
|
||||
private static class Tokener {
|
||||
private String lookahead;
|
||||
private StringTokenizer tokens;
|
||||
public Tokener(String input) {
|
||||
this.tokens = new StringTokenizer(input, DELIM, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch next token. Returns null if there are no more tokens.
|
||||
*/
|
||||
public String nextToken() {
|
||||
if (lookahead!=null) {
|
||||
try {
|
||||
return lookahead;
|
||||
} finally {
|
||||
lookahead = null;
|
||||
}
|
||||
} else if (tokens.hasMoreTokens()) {
|
||||
return tokens.nextToken();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Fetch the next token without consuming it.
|
||||
* Returns null if there are no more tokens.
|
||||
*/
|
||||
public String peekToken() {
|
||||
if (lookahead!=null) {
|
||||
return lookahead;
|
||||
} else if (tokens.hasMoreTokens()) {
|
||||
lookahead = tokens.nextToken();
|
||||
return lookahead;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Tokener input;
|
||||
|
||||
private TypeParser(String input) {
|
||||
this.input = new Tokener(input);
|
||||
}
|
||||
|
||||
public static Type parse(String str) {
|
||||
if (StringUtil.hasText(str)) {
|
||||
return new TypeParser(str).parseType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Type parseType() {
|
||||
String ident = input.nextToken();
|
||||
String token = input.peekToken();
|
||||
if ("<".equals(token)) {
|
||||
ArrayList<Type> params = parseParams();
|
||||
return new Type(ident, params.toArray(new Type[params.size()]));
|
||||
} else {
|
||||
return new Type(ident, null);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Type> parseParams() {
|
||||
skip("<");
|
||||
try {
|
||||
return parseParamList(new ArrayList<Type>());
|
||||
} finally {
|
||||
skip(">");
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Type> parseParamList(ArrayList<Type> params) {
|
||||
//parse params separate by ",'
|
||||
String tok = input.peekToken();
|
||||
if (isIdent(tok)) {
|
||||
params.add(parseType());
|
||||
if (skip(",")) {
|
||||
return parseParamList(params);
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip an expected token, or do nothing if the next token is
|
||||
* something unexpected.
|
||||
* @return whether token was skipped.
|
||||
*/
|
||||
private boolean skip(String expected) {
|
||||
String t = input.peekToken();
|
||||
if (expected.equals(t)) {
|
||||
input.nextToken();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isIdent(String token) {
|
||||
return token!=null && !isSeparator(token);
|
||||
}
|
||||
|
||||
private boolean isSeparator(String token) {
|
||||
if (token!=null && token.length()==1) {
|
||||
int len = DELIM.length();
|
||||
char c = token.charAt(0);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (DELIM.charAt(i)==c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,976 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
import static org.springframework.ide.vscode.util.ArrayUtils.firstElement;
|
||||
import static org.springframework.ide.vscode.util.ArrayUtils.lastElement;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.boot.configurationmetadata.Deprecation;
|
||||
import org.springframework.ide.vscode.boot.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
|
||||
import org.springframework.ide.vscode.boot.properties.util.DeprecationUtil;
|
||||
import org.springframework.ide.vscode.java.Flags;
|
||||
import org.springframework.ide.vscode.java.IField;
|
||||
import org.springframework.ide.vscode.java.IJavaElement;
|
||||
import org.springframework.ide.vscode.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.java.IMethod;
|
||||
import org.springframework.ide.vscode.java.IType;
|
||||
import org.springframework.ide.vscode.util.AlwaysFailingParser;
|
||||
import org.springframework.ide.vscode.util.ArrayUtils;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.util.EnumValueParser;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
import org.springframework.ide.vscode.util.LazyProvider;
|
||||
import org.springframework.ide.vscode.util.Log;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
import org.springframework.ide.vscode.util.ValueParser;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.net.MediaType;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
/**
|
||||
* Utilities to work with types represented as Strings as returned by
|
||||
* Spring config metadata apis.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class TypeUtil {
|
||||
|
||||
private static abstract class RadixableParser implements ValueParser {
|
||||
protected abstract Object parse(String str, int radix);
|
||||
|
||||
@Override
|
||||
public Object parse(String str) {
|
||||
if (str.startsWith("0")) {
|
||||
if (str.startsWith("0x")||str.startsWith("0X")) {
|
||||
return parse(str.substring(2), 16);
|
||||
} else if (str.startsWith("0b") || str.startsWith("0B")) {
|
||||
return parse(str.substring(2), 2);
|
||||
} else {
|
||||
return parse(str, 8);
|
||||
}
|
||||
}
|
||||
return parse(str, 10);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final Object OBJECT_TYPE_NAME = Object.class.getName();
|
||||
private static final String STRING_TYPE_NAME = String.class.getName();
|
||||
private static final String INET_ADDRESS_TYPE_NAME = InetAddress.class.getName();
|
||||
private static final String CLASS_TYPE_NAME = Class.class.getName();
|
||||
|
||||
public enum BeanPropertyNameMode {
|
||||
HYPHENATED(true,false), //bean property name in hyphenated form. E.g 'some-property-name'
|
||||
CAMEL_CASE(false,true), //bean property name in camelCase. E.g. 'somePropertyName'
|
||||
ALIASED(true,true); //use both as aliases of one another.
|
||||
|
||||
private final boolean includesHyphenated;
|
||||
private final boolean includesCamelCase;
|
||||
|
||||
BeanPropertyNameMode(boolean hyphenated, boolean camelCase) {
|
||||
this.includesCamelCase = camelCase;
|
||||
this.includesHyphenated = hyphenated;
|
||||
}
|
||||
|
||||
public boolean includesHyphenated() {
|
||||
return includesHyphenated;
|
||||
}
|
||||
|
||||
public boolean includesCamelCase() {
|
||||
return includesCamelCase;
|
||||
}
|
||||
}
|
||||
|
||||
public enum EnumCaseMode {
|
||||
LOWER_CASE, //convert enum names to lower case
|
||||
ORIGNAL, //keep orignal enum name
|
||||
ALIASED //use both lower-cased and original names as aliases of one another
|
||||
}
|
||||
|
||||
private IJavaProject javaProject;
|
||||
|
||||
public TypeUtil(IJavaProject jp) {
|
||||
//Note javaProject is allowed to be null, but only in unit testing context
|
||||
// (This is so some tests can be run without an explicit jp needing to be created)
|
||||
this.javaProject = jp;
|
||||
}
|
||||
|
||||
|
||||
private static final Map<String, String> PRIMITIVE_TYPE_NAMES = new HashMap<>();
|
||||
private static final Map<String, Type> PRIMITIVE_TO_BOX_TYPE = new HashMap<>();
|
||||
static {
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Boolean", "boolean");
|
||||
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Byte", "byte");
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Short", "short");
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Integer","int");
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Long", "long");
|
||||
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Double", "double");
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Float", "float");
|
||||
|
||||
PRIMITIVE_TYPE_NAMES.put("java.lang.Character", "char");
|
||||
|
||||
for (Entry<String, String> e : PRIMITIVE_TYPE_NAMES.entrySet()) {
|
||||
PRIMITIVE_TO_BOX_TYPE.put(e.getValue(), new Type(e.getKey(), null));
|
||||
}
|
||||
}
|
||||
|
||||
public static final Type INTEGER_TYPE = new Type("java.lang.Integer", null);
|
||||
|
||||
private static final Set<String> ASSIGNABLE_TYPES = new HashSet<>(Arrays.asList(
|
||||
"java.lang.Boolean",
|
||||
"java.lang.String",
|
||||
"java.lang.Short",
|
||||
"java.lang.Integer",
|
||||
"java.lang.Long",
|
||||
"java.lang.Double",
|
||||
"java.lang.Float",
|
||||
"java.lang.Character",
|
||||
"java.lang.Byte",
|
||||
INET_ADDRESS_TYPE_NAME,
|
||||
CLASS_TYPE_NAME,
|
||||
"java.lang.String[]"
|
||||
));
|
||||
|
||||
private static final Set<String> ATOMIC_TYPES = new HashSet<>(PRIMITIVE_TYPE_NAMES.keySet());
|
||||
static {
|
||||
ATOMIC_TYPES.add(INET_ADDRESS_TYPE_NAME);
|
||||
ATOMIC_TYPES.add(STRING_TYPE_NAME);
|
||||
ATOMIC_TYPES.add(CLASS_TYPE_NAME);
|
||||
}
|
||||
|
||||
private static final Map<String, String[]> TYPE_VALUES = new HashMap<>();
|
||||
static {
|
||||
TYPE_VALUES.put("java.lang.Boolean", new String[] { "true", "false" });
|
||||
}
|
||||
|
||||
private static final Map<String,ValueParser> VALUE_PARSERS = new HashMap<>();
|
||||
static {
|
||||
VALUE_PARSERS.put(Byte.class.getName(), new RadixableParser() {
|
||||
public Object parse(String str, int radix) {
|
||||
return Byte.parseByte(str, radix);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Integer.class.getName(), new RadixableParser() {
|
||||
public Object parse(String str, int radix) {
|
||||
return Integer.parseInt(str, radix);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Long.class.getName(), new RadixableParser() {
|
||||
public Object parse(String str, int radix) {
|
||||
return Long.parseLong(str, radix);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Short.class.getName(), new RadixableParser() {
|
||||
public Object parse(String str, int radix) {
|
||||
return Short.parseShort(str, radix);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Double.class.getName(), new ValueParser() {
|
||||
public Object parse(String str) {
|
||||
return Double.parseDouble(str);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Float.class.getName(), new ValueParser() {
|
||||
public Object parse(String str) {
|
||||
return Float.parseFloat(str);
|
||||
}
|
||||
});
|
||||
VALUE_PARSERS.put(Boolean.class.getName(), new ValueParser() {
|
||||
public Object parse(String str) {
|
||||
//The 'more obvious' implementation is too liberal and accepts anything as okay.
|
||||
//return Boolean.parseBoolean(str);
|
||||
str = str.toLowerCase();
|
||||
if (str.equals("true")) {
|
||||
return true;
|
||||
} else if (str.equals("false")) {
|
||||
return false;
|
||||
}
|
||||
throw new IllegalArgumentException("Value should be 'true' or 'false'");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ValueParser getValueParser(Type type) {
|
||||
ValueParser simpleParser = VALUE_PARSERS.get(type.getErasure());
|
||||
if (simpleParser!=null) {
|
||||
return simpleParser;
|
||||
}
|
||||
Collection<StsValueHint> enumValues = getAllowedValues(type, EnumCaseMode.ALIASED);
|
||||
if (enumValues!=null) {
|
||||
//Note, technically if 'enumValues is empty array' this means something different
|
||||
// from when it is null. An empty array means a type that has no values, so
|
||||
// assigning anything to it is an error.
|
||||
return new EnumValueParser(niceTypeName(type), getBareValues(enumValues));
|
||||
}
|
||||
if (isMap(type)) {
|
||||
//Trying to parse map types from scalars is not possible. Thus we
|
||||
// provide a parser that allows throws
|
||||
return new AlwaysFailingParser(niceTypeName(type));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] getBareValues(Collection<StsValueHint> hints) {
|
||||
if (hints!=null) {
|
||||
String[] values = new String[hints.size()];
|
||||
int i = 0;
|
||||
for (StsValueHint h : hints) {
|
||||
values[i++] = h.getValue();
|
||||
}
|
||||
return values;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An array of allowed values for a given type. If an array is returned then
|
||||
* *only* values in the array are valid and using any other value constitutes an error.
|
||||
* This may return null if allowedValues list is unknown or the type is not characterizable
|
||||
* as a simple enumaration of allowed values.
|
||||
* @param caseMode determines whether Enum values are returned in 'lower case form', 'orignal form',
|
||||
* or 'aliased' (meaning both forms are returned).
|
||||
*/
|
||||
public Collection<StsValueHint> getAllowedValues(Type enumType, EnumCaseMode caseMode) {
|
||||
if (enumType!=null) {
|
||||
try {
|
||||
String[] values = TYPE_VALUES.get(enumType.getErasure());
|
||||
if (values!=null) {
|
||||
if (caseMode==EnumCaseMode.ALIASED) {
|
||||
ImmutableSet.Builder<String> aliased = ImmutableSet.builder();
|
||||
aliased.add(values);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
aliased.add(values[i].toUpperCase());
|
||||
}
|
||||
return aliased.build().stream().map(StsValueHint::create).collect(Collectors.toList());
|
||||
} else {
|
||||
return Arrays.stream(values).map(StsValueHint::create).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
IType type = findType(enumType.getErasure());
|
||||
if (type!=null && type.isEnum()) {
|
||||
IField[] fields = type.getFields();
|
||||
|
||||
if (fields!=null) {
|
||||
ImmutableList.Builder<StsValueHint> enums = ImmutableList.builder();
|
||||
boolean addOriginal = caseMode==EnumCaseMode.ORIGNAL||caseMode==EnumCaseMode.ALIASED;
|
||||
boolean addLowerCased = caseMode==EnumCaseMode.LOWER_CASE||caseMode==EnumCaseMode.ALIASED;
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
IField f = fields[i];
|
||||
Provider<HtmlSnippet> jdoc = StsValueHint.javaDocSnippet(f);
|
||||
if (f.isEnumConstant()) {
|
||||
String rawName = f.getElementName();
|
||||
if (addOriginal) {
|
||||
enums.add(StsValueHint.create(rawName, f));
|
||||
}
|
||||
if (addLowerCased) {
|
||||
enums.add(StsValueHint.create(StringUtil.upperCaseToHyphens(rawName), f));
|
||||
}
|
||||
}
|
||||
}
|
||||
return enums.build();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String niceTypeName(Type _type) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
niceTypeName(_type, buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public void niceTypeName(Type type, StringBuilder buf) {
|
||||
if (type==null) {
|
||||
buf.append("null");
|
||||
return;
|
||||
}
|
||||
String typeStr = type.getErasure();
|
||||
String primTypeName = PRIMITIVE_TYPE_NAMES.get(typeStr);
|
||||
if (primTypeName!=null) {
|
||||
buf.append(primTypeName);
|
||||
} else if (typeStr.startsWith("java.lang.")) {
|
||||
buf.append(typeStr.substring("java.lang.".length()));
|
||||
} else if (typeStr.startsWith("java.util.")) {
|
||||
buf.append(typeStr.substring("java.util.".length()));
|
||||
} else {
|
||||
buf.append(typeStr);
|
||||
}
|
||||
if (isEnum(type)) {
|
||||
Collection<StsValueHint> values = getAllowedValues(type, EnumCaseMode.ORIGNAL);
|
||||
if (values!=null && !values.isEmpty()) {
|
||||
buf.append("[");
|
||||
int i = 0;
|
||||
for (StsValueHint hint : values) {
|
||||
if (i>0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append(hint.getValue());
|
||||
i++;
|
||||
if (i>=4) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i<values.size()) {
|
||||
buf.append(", ...");
|
||||
}
|
||||
buf.append("]");
|
||||
}
|
||||
} else if (type.isGeneric()) {
|
||||
Type[] params = type.getParams();
|
||||
buf.append("<");
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (i>0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
niceTypeName(params[i], buf);
|
||||
}
|
||||
buf.append(">");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return true if it is reasonable to navigate given type with '.' notation. This returns true
|
||||
* by default except for some specific cases we assume are not 'dotable' such as Primitive types
|
||||
* and String
|
||||
*/
|
||||
public boolean isDotable(Type type) {
|
||||
String typeName = type.getErasure();
|
||||
if (typeName.equals("java.lang.Object")) {
|
||||
//special case. Treat as 'non dotable' type. This mainly for stuff like logging.level
|
||||
// declared as Map<String,Object> so it would 'eat' the dots into the key.
|
||||
// also it makes sense to treat Object as 'non-dotable' since we cannot determine properties
|
||||
// for such an abstract type (as Object itself has no setters).
|
||||
return false;
|
||||
}
|
||||
return !isAtomic(type);
|
||||
}
|
||||
|
||||
public static boolean isObject(Type type) {
|
||||
return type!=null && OBJECT_TYPE_NAME.equals(type.getErasure());
|
||||
}
|
||||
|
||||
public static boolean isString(Type type) {
|
||||
return type!=null && STRING_TYPE_NAME.equals(type.getErasure());
|
||||
}
|
||||
|
||||
public boolean isAtomic(Type type) {
|
||||
if (type!=null) {
|
||||
String typeName = type.getErasure();
|
||||
return ATOMIC_TYPES.contains(typeName) || isEnum(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if it is valid to
|
||||
* use the notation <name>[<index>]=<value> in property file
|
||||
* for properties of this type.
|
||||
*/
|
||||
public static boolean isBracketable(Type type) {
|
||||
//Note array types where once not considered 'Bracketable'
|
||||
//see: STS-4031
|
||||
|
||||
//However...
|
||||
//Seems that in Boot 1.3 arrays are now 'Bracketable' and funcion much equivalnt to list (even including 'autogrowing' them).
|
||||
//This is actually more logical too.
|
||||
//So '[' notation in props file can be used for either list or arrays (at leats in recent versions of boot).
|
||||
return isArray(type) || isList(type);
|
||||
}
|
||||
|
||||
public static boolean isList(Type type) {
|
||||
//Note: to be really correct we should use JDT infrastructure to resolve
|
||||
//type in project classpath instead of using Java reflection.
|
||||
//However, use reflection here is okay assuming types we care about
|
||||
//are part of JRE standard libraries. Using eclipse 'type hirearchy' would
|
||||
//also potentialy be very slow.
|
||||
if (type!=null) {
|
||||
String erasure = type.getErasure();
|
||||
try {
|
||||
Class<?> erasureClass = Class.forName(erasure);
|
||||
return List.class.isAssignableFrom(erasureClass);
|
||||
} catch (Exception e) {
|
||||
//type not resolveable assume its not 'array like'
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if type can be treated / represented as a sequence node in .yml file
|
||||
*/
|
||||
public static boolean isSequencable(Type type) {
|
||||
return isList(type) || isArray(type);
|
||||
}
|
||||
|
||||
public static boolean isArray(Type type) {
|
||||
return type!=null && type.getErasure().endsWith("[]");
|
||||
}
|
||||
|
||||
public static boolean isMap(Type type) {
|
||||
//Note: to be really correct we should use JDT infrastructure to resolve
|
||||
//type in project classpath instead of using Java reflection.
|
||||
//However, use reflection here is okay assuming types we care about
|
||||
//are part of JRE standard libraries. Using eclipse 'type hirearchy' would
|
||||
//also potentialy be very slow.
|
||||
if (type!=null) {
|
||||
String erasure = type.getErasure();
|
||||
try {
|
||||
Class<?> erasureClass = Class.forName(erasure);
|
||||
return Map.class.isAssignableFrom(erasureClass);
|
||||
} catch (Exception e) {
|
||||
//type not resolveable
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get domain type for a map or list generic type.
|
||||
*/
|
||||
public static Type getDomainType(Type type) {
|
||||
if (isArray(type)) {
|
||||
return getArrayDomainType(type);
|
||||
} else {
|
||||
return lastElement(type.getParams());
|
||||
}
|
||||
}
|
||||
|
||||
private static Type getArrayDomainType(Type type) {
|
||||
if (type!=null) {
|
||||
String fullName = type.getErasure();
|
||||
Assert.isLegal(fullName.endsWith("[]"));
|
||||
String elName = fullName.substring(0, fullName.length()-2);
|
||||
return normalizePrimitiveType(new Type(elName, null));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a type which is a 'primitive' type like 'int', 'long' etc. to its
|
||||
* corresponding 'Boxed' type. If the type isn't a primitive type then
|
||||
* just return it unchanged.
|
||||
*/
|
||||
private static Type normalizePrimitiveType(Type type) {
|
||||
if (type!=null) {
|
||||
String name = type.getErasure();
|
||||
Type boxType = PRIMITIVE_TO_BOX_TYPE.get(name);
|
||||
if (boxType!=null) {
|
||||
return boxType;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public Type getKeyType(Type mapOrArrayType) {
|
||||
if (isSequencable(mapOrArrayType)) {
|
||||
return INTEGER_TYPE;
|
||||
} else {
|
||||
//assumed to be a map
|
||||
return firstElement(mapOrArrayType.getParams());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAssignableType(Type type) {
|
||||
return ASSIGNABLE_TYPES.contains(type.getErasure())
|
||||
|| isEnum(type)
|
||||
|| isAssignableList(type);
|
||||
}
|
||||
|
||||
private boolean isAssignableList(Type type) {
|
||||
//TODO: isBracketable means 'isList' right now, but this may not be
|
||||
// the case in the future.
|
||||
if (isBracketable(type)) {
|
||||
Type domainType = getDomainType(type);
|
||||
return isAtomic(domainType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEnum(Type type) {
|
||||
try {
|
||||
IType eclipseType = findType(type.getErasure());
|
||||
if (eclipseType!=null) {
|
||||
return eclipseType.isEnum();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private IType findType(String typeName) {
|
||||
try {
|
||||
if (javaProject!=null) {
|
||||
return javaProject.findType(typeName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IType findType(Type beanType) {
|
||||
return findType(beanType.getErasure());
|
||||
}
|
||||
|
||||
private static final String[] NO_PARAMS = new String[0];
|
||||
private static final Map<String, ValueProviderStrategy> VALUE_HINTERS = new HashMap<>();
|
||||
static {
|
||||
valueHints("java.nio.charset.Charset", new LazyProvider<String[]>() {
|
||||
@Override
|
||||
protected String[] compute() {
|
||||
Set<String> charsets = Charset.availableCharsets().keySet();
|
||||
return charsets.toArray(new String[charsets.size()]);
|
||||
}
|
||||
});
|
||||
valueHints("java.util.Locale", new LazyProvider<String[]>() {
|
||||
@Override
|
||||
protected String[] compute() {
|
||||
Locale[] locales = SimpleDateFormat.getAvailableLocales();
|
||||
String[] names = new String[locales.length];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = locales[i].toString();
|
||||
}
|
||||
return names;
|
||||
}
|
||||
});
|
||||
valueHints("org.springframework.util.MimeType", new LazyProvider<String[]>() {
|
||||
@Override
|
||||
protected String[] compute() {
|
||||
try {
|
||||
Field f = MediaType.class.getDeclaredField("KNOWN_TYPES");
|
||||
f.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<MediaType, MediaType> map = (Map<MediaType, MediaType>) f.get(null);
|
||||
TreeSet<String> mediaTypes = new TreeSet<>();
|
||||
for (MediaType m : map.keySet()) {
|
||||
mediaTypes.add(m.toString());
|
||||
}
|
||||
return mediaTypes.toArray(new String[mediaTypes.size()]);
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
// valueHints("org.springframework.core.io.Resource", new ResourceHintProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine properties that are setable on object of given type.
|
||||
* <p>
|
||||
* Note that this may return both null or an empty list, but they mean
|
||||
* different things. Null means that the properties on the object are not known,
|
||||
* and therefore reconciling should not check property validity. On the other hand
|
||||
* returning an empty list means that there are no properties. In this case,
|
||||
* accessing properties is invalid and reconciler should show an error message
|
||||
* for any property access.
|
||||
*
|
||||
* @return A list of known properties or null if the list of properties is unknown.
|
||||
*/
|
||||
public List<TypedProperty> getProperties(Type type, EnumCaseMode enumMode, BeanPropertyNameMode beanMode) {
|
||||
if (type==null) {
|
||||
return null;
|
||||
}
|
||||
if (!isDotable(type)) {
|
||||
//If dot navigation is not valid then really this is just like saying the type has no properties.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (isMap(type)) {
|
||||
Type keyType = getKeyType(type);
|
||||
if (keyType!=null) {
|
||||
Collection<StsValueHint> keyHints = getAllowedValues(keyType, enumMode);
|
||||
if (CollectionUtil.hasElements(keyHints)) {
|
||||
Type valueType = getDomainType(type);
|
||||
ArrayList<TypedProperty> properties = new ArrayList<>(keyHints.size());
|
||||
for (StsValueHint hint : keyHints) {
|
||||
String propName = hint.getValue();
|
||||
properties.add(new TypedProperty(propName, valueType, hint.getDescriptionProvider(), hint.getDeprecation()));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String typename = type.getErasure();
|
||||
IType eclipseType = findType(typename);
|
||||
|
||||
//TODO: handle type parameters.
|
||||
if (eclipseType!=null) {
|
||||
List<IMethod> getters = getGetterMethods(eclipseType);
|
||||
//TODO: getters inherited from super classes?
|
||||
if (getters!=null && !getters.isEmpty()) {
|
||||
ArrayList<TypedProperty> properties = new ArrayList<>(getters.size());
|
||||
for (IMethod m : getters) {
|
||||
Deprecation deprecation = DeprecationUtil.extract(m);
|
||||
Type propType = null;
|
||||
try {
|
||||
propType = Type.fromSignature(m.getReturnType(), eclipseType);
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
if (beanMode.includesHyphenated()) {
|
||||
properties.add(new TypedProperty(getterOrSetterNameToProperty(m.getElementName()), propType, deprecation));
|
||||
}
|
||||
if (beanMode.includesCamelCase()) {
|
||||
properties.add(new TypedProperty(getterOrSetterNameToCamelName(m.getElementName()), propType, deprecation));
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a strategy for providing value hints with a given typeName.
|
||||
*/
|
||||
public static void valueHints(String typeName, ValueProviderStrategy provider) {
|
||||
Assert.isLegal(!VALUE_HINTERS.containsKey(typeName)); //Only one value hinter per type is supported at the moment
|
||||
ATOMIC_TYPES.add(typeName); //valueHints typically implies that the type should be treated as atomic as well.
|
||||
ASSIGNABLE_TYPES.add(typeName); //valueHints typically implies that the type should be treated as atomic as well.
|
||||
VALUE_HINTERS.put(typeName, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a strategy for providing value hints with a given typeName.
|
||||
*/
|
||||
public static void valueHints(String typeName, Provider<String[]> provider) {
|
||||
valueHints(typeName, new ValueProviderStrategy() {
|
||||
@Override
|
||||
public Flux<StsValueHint> getValues(IJavaProject javaProject, String query) {
|
||||
String[] values = provider.get();
|
||||
if (ArrayUtils.hasElements(values)) {
|
||||
return Flux.fromArray(values)
|
||||
.map(StsValueHint::create);
|
||||
}
|
||||
return Flux.empty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getterOrSetterNameToProperty(String name) {
|
||||
String camelName = getterOrSetterNameToCamelName(name);
|
||||
return StringUtil.camelCaseToHyphens(camelName);
|
||||
}
|
||||
|
||||
public String getterOrSetterNameToCamelName(String name) {
|
||||
Assert.isLegal(name.startsWith("set") || name.startsWith("get") || name.startsWith("is"));
|
||||
int prefixLen = name.startsWith("is") ? 2 : 3;
|
||||
String camelName = Character.toLowerCase(name.charAt(prefixLen)) + name.substring(prefixLen+1);
|
||||
return camelName;
|
||||
}
|
||||
|
||||
private List<IMethod> getGetterMethods(IType eclipseType) {
|
||||
try {
|
||||
if (eclipseType!=null && eclipseType.isClass()) {
|
||||
IMethod[] allMethods = eclipseType.getMethods();
|
||||
if (ArrayUtils.hasElements(allMethods)) {
|
||||
ArrayList<IMethod> getters = new ArrayList<>();
|
||||
for (IMethod m : allMethods) {
|
||||
if (!isStatic(m) && isPublic(m)) {
|
||||
String mname = m.getElementName();
|
||||
if (
|
||||
(mname.startsWith("get") && mname.length()>=4) ||
|
||||
(mname.startsWith("is") && mname.length()>=3)
|
||||
) {
|
||||
//Need at least x chars or the property name will be empty.
|
||||
String sig = m.getSignature();
|
||||
int numParams = Signature.getParameterCount(sig);
|
||||
if (numParams==0) {
|
||||
getters.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return getters;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// private List<IMethod> getSetterMethods(IType eclipseType) {
|
||||
// try {
|
||||
// if (eclipseType!=null && eclipseType.isClass()) {
|
||||
// IMethod[] allMethods = eclipseType.getMethods();
|
||||
// if (ArrayUtils.hasElements(allMethods)) {
|
||||
// ArrayList<IMethod> setters = new ArrayList<IMethod>();
|
||||
// for (IMethod m : allMethods) {
|
||||
// String mname = m.getElementName();
|
||||
// if (mname.startsWith("set") && mname.length()>=4) {
|
||||
// //Need at least 4 chars or the property name will be empty.
|
||||
// String sig = m.getSignature();
|
||||
// int numParams = Signature.getParameterCount(sig);
|
||||
// if (numParams==1) {
|
||||
// setters.add(m);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return setters;
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// BootActivator.log(e);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
private boolean isStatic(IMethod m) {
|
||||
try {
|
||||
return Flags.isStatic(m.getFlags());
|
||||
} catch (Exception e) {
|
||||
//Couldn't determine if it was public or not... let's assume it was NOT
|
||||
// (will result in potentially more CA completions)
|
||||
Log.log(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPublic(IMethod m) {
|
||||
try {
|
||||
return m.getDeclaringType().isInterface()
|
||||
|| Flags.isPublic(m.getFlags());
|
||||
} catch (Exception e) {
|
||||
//Couldn't determine if it was public or not... let's assume it WAS
|
||||
// (will result in potentially more CA completions)
|
||||
Log.log(e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, TypedProperty> getPropertiesMap(Type type, EnumCaseMode enumMode, BeanPropertyNameMode beanMode) {
|
||||
//TODO: optimize, produce directly as a map instead of
|
||||
// first creating list and then coverting it.
|
||||
List<TypedProperty> list = getProperties(type, enumMode, beanMode);
|
||||
if (list!=null) {
|
||||
Map<String, TypedProperty> map = new HashMap<>();
|
||||
for (TypedProperty p : list) {
|
||||
map.put(p.getName(), p);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe ne null in some contexts. In such context functionality will be limited because
|
||||
* types can not be resolved.
|
||||
*/
|
||||
public IJavaProject getJavaProject() {
|
||||
return javaProject;
|
||||
}
|
||||
|
||||
public IField getField(Type beanType, String propName) {
|
||||
IType type = findType(beanType);
|
||||
return getExactField(type, propName);
|
||||
}
|
||||
|
||||
protected IField getExactField(IType type, String fieldName) {
|
||||
IField f = type.getField(StringUtil.hyphensToCamelCase(fieldName, false));
|
||||
if (f!=null && f.exists()) {
|
||||
return f;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IField getEnumConstant(Type enumType, String propName) {
|
||||
IType type = findType(enumType);
|
||||
//1: if propname is already spelled exactly...
|
||||
IField f = getExactField(type, propName);
|
||||
if (f!=null) return f;
|
||||
|
||||
//2: most likely enum constant is upper-case form of propname
|
||||
String fieldName = StringUtil.hyphensToUpperCase(propName);
|
||||
return getExactField(type, fieldName);
|
||||
}
|
||||
|
||||
|
||||
public IMethod getSetter(Type beanType, String propName) {
|
||||
try {
|
||||
String setterName = "set" + StringUtil.hyphensToCamelCase(propName, true);
|
||||
IType type = findType(beanType);
|
||||
for (IMethod m : type.getMethods()) {
|
||||
if (setterName.equals(m.getElementName())) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IJavaElement getGetter(Type beanType, String propName) {
|
||||
String getterName = "get" + StringUtil.hyphensToCamelCase(propName, true);
|
||||
IType type = findType(beanType);
|
||||
|
||||
IMethod m = type.getMethod(getterName, NO_PARAMS);
|
||||
if (m.exists()) {
|
||||
return m;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String deprecatedPropertyMessage(String name, String contextType, String replace, String reason) {
|
||||
StringBuilder msg = new StringBuilder("Property '"+name+"'");
|
||||
if (StringUtil.hasText(contextType)) {
|
||||
msg.append(" of type '"+contextType+"'");
|
||||
}
|
||||
boolean hasReplace = StringUtil.hasText(replace);
|
||||
boolean hasReason = StringUtil.hasText(reason);
|
||||
if (!hasReplace && !hasReason) {
|
||||
msg.append(" is Deprecated!");
|
||||
} else {
|
||||
msg.append(" is Deprecated: ");
|
||||
if (hasReplace) {
|
||||
msg.append("Use '"+ replace +"' instead.");
|
||||
if (hasReason) {
|
||||
msg.append(" Reason: ");
|
||||
}
|
||||
}
|
||||
if (hasReason) {
|
||||
msg.append(reason);
|
||||
}
|
||||
}
|
||||
return msg.toString();
|
||||
}
|
||||
|
||||
public Collection<StsValueHint> getHintValues(Type type, String query, EnumCaseMode enumCaseMode) {
|
||||
if (type!=null) {
|
||||
Collection<StsValueHint> allowed = getAllowedValues(type, enumCaseMode);
|
||||
if (allowed!=null) {
|
||||
return allowed;
|
||||
}
|
||||
ValueProviderStrategy valueHinter = VALUE_HINTERS.get(type.getErasure());
|
||||
if (valueHinter!=null) {
|
||||
return valueHinter.getValuesNow(javaProject, query);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the dimensionality of a collection-like type (i.e. a Map or List). The dimensionality
|
||||
* is essentialy how many succesive 'indexing' operations need to be applied before reasing the actual elements.
|
||||
* <p>
|
||||
* For examle:
|
||||
* List<String> -> 1
|
||||
* List<List<String>> -> 2
|
||||
* List<List<List<String>>> -> 2
|
||||
* Map<*,List<String>> -> 2
|
||||
*/
|
||||
public static int getDimensionality(Type type) {
|
||||
int dim = 0;
|
||||
while (isSequencable(type) || isMap(type)) {
|
||||
dim++;
|
||||
type = getDomainType(type);
|
||||
}
|
||||
return dim;
|
||||
}
|
||||
|
||||
public static boolean isClass(Type type) {
|
||||
if (type!=null) {
|
||||
return CLASS_TYPE_NAME.equals(type.getErasure());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Addapting our interface so it is compatible with YTypeUtil
|
||||
//
|
||||
// This allows our types to be used by the more generic stuff from the 'editor.support' plugin.
|
||||
//
|
||||
// Note, it may be possible to avoid having these 'adaptor' methods by making YTypeUtil a paramerized
|
||||
// type. I.e something like "interface YTypeUtil<T extends YType>.
|
||||
// Paramterizations like that tend to propagate fire and wide in the code and make for complicated
|
||||
// signatures. For now using these bredging methods is simpler if perhaps a bit more error prone.
|
||||
|
||||
// @Override
|
||||
// public boolean isAtomic(YType type) {
|
||||
// return isAtomic((Type)type);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isMap(YType type) {
|
||||
// return isMap((Type)type);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean isSequencable(YType type) {
|
||||
// return isSequencable((Type)type);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public YType getDomainType(YType type) {
|
||||
// return getDomainType((Type)type);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String[] getHintValues(YType type) {
|
||||
// return getAllowedValues((Type) type, EnumCaseMode.ALIASED);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// @Override
|
||||
// public List<YTypedProperty> getProperties(YType type) {
|
||||
// //Dirty hack, passing this through a raw type to bypass the java type system
|
||||
// //complaining the List<TypedProperty> is not compatible with List<YTypedProperty>
|
||||
// //This dirty and 'illegal' conversion is okay because the list is only used for reading.
|
||||
// @SuppressWarnings("rawtypes")
|
||||
// List props = getProperties((Type)type, EnumCaseMode.ALIASED, BeanPropertyNameMode.ALIASED);
|
||||
// return Collections.unmodifiableList(props);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// @Override
|
||||
// public Map<String, YTypedProperty> getPropertiesMap(YType type) {
|
||||
// //Dirty hack, see comment in getProperties(YType)
|
||||
// @SuppressWarnings("rawtypes")
|
||||
// Map map = getPropertiesMap((Type)type, EnumCaseMode.ALIASED, BeanPropertyNameMode.ALIASED);
|
||||
// return Collections.unmodifiableMap(map);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String niceTypeName(YType type) {
|
||||
// return niceTypeName((Type)type);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public YType getKeyType(YType type) {
|
||||
// return getKeyType((Type)type);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TypeUtilProvider {
|
||||
TypeUtil getTypeUtil(IDocument doc);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.boot.configurationmetadata.Deprecation;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypedProperty;
|
||||
import org.springframework.ide.vscode.yaml.util.DescriptionProviders;
|
||||
|
||||
/**
|
||||
* Represents a property on a Type that can be accessed by name.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class TypedProperty implements YTypedProperty {
|
||||
|
||||
/**
|
||||
* The name of the property
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The type of value associated with the property.
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* Provides a description for this property.
|
||||
*/
|
||||
private final Provider<HtmlSnippet> descriptionProvider;
|
||||
|
||||
private final Deprecation deprecation;
|
||||
|
||||
public TypedProperty(String name, Type type, Deprecation deprecation) {
|
||||
this(name, type, DescriptionProviders.NO_DESCRIPTION, deprecation);
|
||||
}
|
||||
|
||||
public TypedProperty(String name, Type type, Provider<HtmlSnippet> descriptionProvider, Deprecation deprecation) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.descriptionProvider = descriptionProvider;
|
||||
this.deprecation = deprecation;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + "::" + type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlSnippet getDescription() {
|
||||
//TODO: real implementation that somehow gets this from somewhere (i.e. the JavaDoc)
|
||||
// Note that presently the application.yml and application.properties editor do not actually
|
||||
// use this description provider but produce hover infos in a different way (so this is only
|
||||
// used in Schema-based content assist, reconciling and hovering.
|
||||
//So in that sense putting a good implementation here is kind of pointless right now.
|
||||
//More refactoring needs to be done to also make use of this.
|
||||
return descriptionProvider.get();
|
||||
}
|
||||
|
||||
public static Type typeOf(TypedProperty typedProperty) {
|
||||
if (typedProperty!=null) {
|
||||
return typedProperty.getType();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isDeprecated() {
|
||||
return deprecation!=null;
|
||||
}
|
||||
|
||||
public String getDeprecationReplacement() {
|
||||
if (deprecation!=null) {
|
||||
return deprecation.getReplacement();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getDeprecationReason() {
|
||||
if (deprecation!=null) {
|
||||
return deprecation.getReason();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Deprecation getDeprecation() {
|
||||
return deprecation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.properties.util;
|
||||
|
||||
import org.springframework.boot.configurationmetadata.Deprecation;
|
||||
import org.springframework.ide.vscode.java.IAnnotatable;
|
||||
import org.springframework.ide.vscode.java.IAnnotation;
|
||||
import org.springframework.ide.vscode.java.IJavaElement;
|
||||
import org.springframework.ide.vscode.java.IMemberValuePair;
|
||||
import org.springframework.ide.vscode.util.Log;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
public class DeprecationUtil {
|
||||
|
||||
private static final ImmutableSet<String> DEPRECATED_ANOT_NAMES = ImmutableSet.of(
|
||||
"org.springframework.boot.context.properties.DeprecatedConfigurationProperty",
|
||||
"DeprecatedConfigurationProperty",
|
||||
"java.lang.Deprecated",
|
||||
"Deprecated"
|
||||
);
|
||||
|
||||
/**
|
||||
* Extract {@link Deprecation} info from annotations on a {@link IJavaElement}
|
||||
*/
|
||||
public static Deprecation extract(IJavaElement je) {
|
||||
if (je instanceof IAnnotatable) {
|
||||
return extract((IAnnotatable)je);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract {@link Deprecation} info from annotations on a {@link IJavaElement}
|
||||
*/
|
||||
private static Deprecation extract(IAnnotatable m) {
|
||||
try {
|
||||
for (IAnnotation a : m.getAnnotations()) {
|
||||
if (DEPRECATED_ANOT_NAMES.contains(a.getElementName())) {
|
||||
Deprecation d = new Deprecation();
|
||||
for (IMemberValuePair pair : a.getMemberValuePairs()) {
|
||||
String name = pair.getMemberName();
|
||||
if (name.equals("reason")) {
|
||||
d.setReason((String) pair.getValue());
|
||||
} else if (name.equals("replacement")) {
|
||||
d.setReplacement((String) pair.getValue());
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
36
vscode-extensions/commons/commons-java/.classpath
Normal file
36
vscode-extensions/commons/commons-java/.classpath
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
vscode-extensions/commons/commons-java/.project
Normal file
23
vscode-extensions/commons/commons-java/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>commons-java</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
22
vscode-extensions/commons/commons-java/pom.xml
Normal file
22
vscode-extensions/commons/commons-java/pom.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<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>
|
||||
<artifactId>commons-java</artifactId>
|
||||
<name>commons-java</name>
|
||||
<description>Common code related to 'accessing Java knowledge'</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,195 @@
|
||||
package org.springframework.ide.vscode.boot.properties.metadata.types;
|
||||
|
||||
public class Signature {
|
||||
|
||||
//These are the bits of JDTs 'Signature' class. Only we copied the method decls
|
||||
// of stuff we actually use
|
||||
|
||||
//TODO: For performamce reason, JDT probably works with String or even naked char[] instead
|
||||
// of wrapping these in a proper 'TypeSignature' or 'MethodSignature' object. But probably we should
|
||||
// do the proper wrapping and abstract out a interface for these types. A 'client'
|
||||
// using 'Java knowledge' should not have to directly be dealing with the JVM method and
|
||||
// type signature strings.
|
||||
|
||||
/**
|
||||
* Kind constant for a class type signature.
|
||||
* @see #getTypeSignatureKind(String)
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int CLASS_TYPE_SIGNATURE = 1;
|
||||
|
||||
/**
|
||||
* Kind constant for an array type signature.
|
||||
* @see #getTypeSignatureKind(String)
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int ARRAY_TYPE_SIGNATURE = 4;
|
||||
|
||||
/**
|
||||
* Character constant indicating the start of an unresolved, named type in a
|
||||
* signature. Value is <code>'Q'</code>.
|
||||
*/
|
||||
public static final char C_UNRESOLVED = 'Q';
|
||||
//TODO: unless we use JDT to work with suource-types we probably don't see these?
|
||||
|
||||
/**
|
||||
* Returns the kind of type signature encoded by the given string.
|
||||
*
|
||||
* @param typeSignature the type signature string
|
||||
* @return the kind of type signature; one of the kind constants:
|
||||
* {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
|
||||
* {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
|
||||
* or (since 3.1) {@link #WILDCARD_TYPE_SIGNATURE} or {@link #CAPTURE_TYPE_SIGNATURE}
|
||||
* or (since 3.7) {@link #INTERSECTION_TYPE_SIGNATURE}
|
||||
* @exception IllegalArgumentException if this is not a type signature
|
||||
* @since 3.0
|
||||
*/
|
||||
public static int getTypeSignatureKind(String typeSignature) {
|
||||
return getTypeSignatureKind(typeSignature.toCharArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the kind of type signature encoded by the given string.
|
||||
*
|
||||
* @param typeSignature the type signature string
|
||||
* @return the kind of type signature; one of the kind constants:
|
||||
* {@link #ARRAY_TYPE_SIGNATURE}, {@link #CLASS_TYPE_SIGNATURE},
|
||||
* {@link #BASE_TYPE_SIGNATURE}, or {@link #TYPE_VARIABLE_SIGNATURE},
|
||||
* or (since 3.1) {@link #WILDCARD_TYPE_SIGNATURE} or {@link #CAPTURE_TYPE_SIGNATURE},
|
||||
* or (since 3.7) {@link #INTERSECTION_TYPE_SIGNATURE}
|
||||
* @exception IllegalArgumentException if this is not a type signature
|
||||
* @since 3.0
|
||||
*/
|
||||
public static int getTypeSignatureKind(char[] typeSignature) {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the type erasure signature from the given parameterized type signature.
|
||||
* Returns the given type signature if it is not parameterized.
|
||||
*
|
||||
* @param parameterizedTypeSignature the parameterized type signature
|
||||
* @return the signature of the type erasure
|
||||
* @exception IllegalArgumentException if the signature is syntactically
|
||||
* incorrect
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public static String getTypeErasure(String parameterizedTypeSignature) {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns package fragment of a type signature. The package fragment separator must be '.'
|
||||
* and the type fragment separator must be '$'.
|
||||
* <p>
|
||||
* For example:
|
||||
* <pre>
|
||||
* <code>
|
||||
* getSignatureQualifier("Ljava.util.Map$Entry") -> "java.util"
|
||||
* </code>
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @param typeSignature the type signature
|
||||
* @return the package fragment (separators are '.')
|
||||
* @since 3.1
|
||||
*/
|
||||
public static String getSignatureQualifier(String typeSignature) {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns type fragment of a type signature. The package fragment separator must be '.'
|
||||
* and the type fragment separator must be '$'.
|
||||
* <p>
|
||||
* For example:
|
||||
* <pre>
|
||||
* <code>
|
||||
* getSignatureSimpleName("Ljava.util.Map$Entry") -> "Map.Entry"
|
||||
* </code>
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @param typeSignature the type signature
|
||||
* @return the type fragment (separators are '.')
|
||||
* @since 3.1
|
||||
*/
|
||||
public static String getSignatureSimpleName(String typeSignature) {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the type parameter signatures from the given method or type signature.
|
||||
* The method or type signature is expected to be dot-based.
|
||||
*
|
||||
* @param methodOrTypeSignature the method or type signature
|
||||
* @return the list of type parameter signatures
|
||||
* @exception IllegalArgumentException if the signature is syntactically
|
||||
* incorrect
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public static String[] getTypeParameters(String methodOrTypeSignature) throws IllegalArgumentException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the type argument signatures from the given type signature.
|
||||
* Returns an empty array if the type signature is not a parameterized type signature.
|
||||
*
|
||||
* @param parameterizedTypeSignature the parameterized type signature
|
||||
* @return the signatures of the type arguments
|
||||
* @exception IllegalArgumentException if the signature is syntactically incorrect
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
public static String[] getTypeArguments(String parameterizedTypeSignature) throws IllegalArgumentException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type signature without any array nesting.
|
||||
* <p>
|
||||
* For example:
|
||||
* <pre>
|
||||
* <code>
|
||||
* getElementType("[[I") --> "I".
|
||||
* </code>
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @param typeSignature the type signature
|
||||
* @return the type signature without arrays
|
||||
* @exception IllegalArgumentException if the signature is not syntactically
|
||||
* correct
|
||||
*/
|
||||
public static String getElementType(String typeSignature) throws IllegalArgumentException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array count (array nesting depth) of the given type signature.
|
||||
*
|
||||
* @param typeSignature the type signature
|
||||
* @return the array nesting depth, or 0 if not an array
|
||||
* @exception IllegalArgumentException if the signature is not syntactically
|
||||
* correct
|
||||
*/
|
||||
public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of parameter types in the given method signature.
|
||||
*
|
||||
* @param methodSignature the method signature
|
||||
* @return the number of parameters
|
||||
* @exception IllegalArgumentException if the signature is not syntactically
|
||||
* correct
|
||||
*/
|
||||
public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2014 IBM Corporation and others.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* Jesper S Moller - Contributions for
|
||||
* Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
|
||||
* Bug 406982 - [1.8][compiler] Generation of MethodParameters Attribute in classfile
|
||||
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
|
||||
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface ClassFileConstants {
|
||||
|
||||
int AccDefault = 0;
|
||||
/*
|
||||
* Modifiers
|
||||
*/
|
||||
int AccPublic = 0x0001;
|
||||
int AccPrivate = 0x0002;
|
||||
int AccProtected = 0x0004;
|
||||
int AccStatic = 0x0008;
|
||||
int AccFinal = 0x0010;
|
||||
int AccSynchronized = 0x0020;
|
||||
int AccVolatile = 0x0040;
|
||||
int AccBridge = 0x0040;
|
||||
int AccTransient = 0x0080;
|
||||
int AccVarargs = 0x0080;
|
||||
int AccNative = 0x0100;
|
||||
int AccInterface = 0x0200;
|
||||
int AccAbstract = 0x0400;
|
||||
int AccStrictfp = 0x0800;
|
||||
int AccSynthetic = 0x1000;
|
||||
int AccAnnotation = 0x2000;
|
||||
int AccEnum = 0x4000;
|
||||
|
||||
/**
|
||||
* From classfile version 52 (compliance 1.8 up), meaning that a formal parameter is mandated
|
||||
* by a language specification, so all compilers for the language must emit it.
|
||||
*/
|
||||
int AccMandated = 0x8000;
|
||||
|
||||
|
||||
/**
|
||||
* Other VM flags.
|
||||
*/
|
||||
int AccSuper = 0x0020;
|
||||
|
||||
// /**
|
||||
// * Extra flags for types and members attributes (not from the JVMS, should have been defined in ExtraCompilerModifiers).
|
||||
// */
|
||||
// int AccAnnotationDefault = ASTNode.Bit18; // indicate presence of an attribute "DefaultValue" (annotation method)
|
||||
// int AccDeprecated = ASTNode.Bit21; // indicate presence of an attribute "Deprecated"
|
||||
|
||||
int Utf8Tag = 1;
|
||||
int IntegerTag = 3;
|
||||
int FloatTag = 4;
|
||||
int LongTag = 5;
|
||||
int DoubleTag = 6;
|
||||
int ClassTag = 7;
|
||||
int StringTag = 8;
|
||||
int FieldRefTag = 9;
|
||||
int MethodRefTag = 10;
|
||||
int InterfaceMethodRefTag = 11;
|
||||
int NameAndTypeTag = 12;
|
||||
int MethodHandleTag = 15;
|
||||
int MethodTypeTag = 16;
|
||||
int InvokeDynamicTag = 18;
|
||||
|
||||
int ConstantMethodRefFixedSize = 5;
|
||||
int ConstantClassFixedSize = 3;
|
||||
int ConstantDoubleFixedSize = 9;
|
||||
int ConstantFieldRefFixedSize = 5;
|
||||
int ConstantFloatFixedSize = 5;
|
||||
int ConstantIntegerFixedSize = 5;
|
||||
int ConstantInterfaceMethodRefFixedSize = 5;
|
||||
int ConstantLongFixedSize = 9;
|
||||
int ConstantStringFixedSize = 3;
|
||||
int ConstantUtf8FixedSize = 3;
|
||||
int ConstantNameAndTypeFixedSize = 5;
|
||||
int ConstantMethodHandleFixedSize = 4;
|
||||
int ConstantMethodTypeFixedSize = 3;
|
||||
int ConstantInvokeDynamicFixedSize = 5;
|
||||
|
||||
// JVMS 4.4.8
|
||||
int MethodHandleRefKindGetField = 1;
|
||||
int MethodHandleRefKindGetStatic = 2;
|
||||
int MethodHandleRefKindPutField = 3;
|
||||
int MethodHandleRefKindPutStatic = 4;
|
||||
int MethodHandleRefKindInvokeVirtual = 5;
|
||||
int MethodHandleRefKindInvokeStatic = 6;
|
||||
int MethodHandleRefKindInvokeSpecial = 7;
|
||||
int MethodHandleRefKindNewInvokeSpecial = 8;
|
||||
int MethodHandleRefKindInvokeInterface = 9;
|
||||
|
||||
int MAJOR_VERSION_1_1 = 45;
|
||||
int MAJOR_VERSION_1_2 = 46;
|
||||
int MAJOR_VERSION_1_3 = 47;
|
||||
int MAJOR_VERSION_1_4 = 48;
|
||||
int MAJOR_VERSION_1_5 = 49;
|
||||
int MAJOR_VERSION_1_6 = 50;
|
||||
int MAJOR_VERSION_1_7 = 51;
|
||||
int MAJOR_VERSION_1_8 = 52;
|
||||
int MAJOR_VERSION_1_9 = 53; // This might change
|
||||
|
||||
int MINOR_VERSION_0 = 0;
|
||||
int MINOR_VERSION_1 = 1;
|
||||
int MINOR_VERSION_2 = 2;
|
||||
int MINOR_VERSION_3 = 3;
|
||||
int MINOR_VERSION_4 = 4;
|
||||
|
||||
// JDK 1.1 -> 1.9, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
|
||||
// 16 unsigned bits for major, then 16 bits for minor
|
||||
long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3
|
||||
long JDK1_2 = ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_3 = ((long)ClassFileConstants.MAJOR_VERSION_1_3 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_4 = ((long)ClassFileConstants.MAJOR_VERSION_1_4 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_5 = ((long)ClassFileConstants.MAJOR_VERSION_1_5 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_6 = ((long)ClassFileConstants.MAJOR_VERSION_1_6 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_7 = ((long)ClassFileConstants.MAJOR_VERSION_1_7 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_8 = ((long)ClassFileConstants.MAJOR_VERSION_1_8 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
long JDK1_9 = ((long)ClassFileConstants.MAJOR_VERSION_1_9 << 16) + ClassFileConstants.MINOR_VERSION_0;
|
||||
|
||||
/*
|
||||
* cldc1.1 is 45.3, but we modify it to be different from JDK1_1.
|
||||
* In the code gen, we will generate the same target value as JDK1_1
|
||||
*/
|
||||
long CLDC_1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_4;
|
||||
|
||||
// jdk level used to denote future releases: optional behavior is not enabled for now, but may become so. In order to enable these,
|
||||
// search for references to this constant, and change it to one of the official JDT constants above.
|
||||
long JDK_DEFERRED = Long.MAX_VALUE;
|
||||
|
||||
int INT_ARRAY = 10;
|
||||
int BYTE_ARRAY = 8;
|
||||
int BOOLEAN_ARRAY = 4;
|
||||
int SHORT_ARRAY = 9;
|
||||
int CHAR_ARRAY = 5;
|
||||
int LONG_ARRAY = 11;
|
||||
int FLOAT_ARRAY = 6;
|
||||
int DOUBLE_ARRAY = 7;
|
||||
|
||||
// Debug attributes
|
||||
int ATTR_SOURCE = 0x1; // SourceFileAttribute
|
||||
int ATTR_LINES = 0x2; // LineNumberAttribute
|
||||
int ATTR_VARS = 0x4; // LocalVariableTableAttribute
|
||||
int ATTR_STACK_MAP_TABLE = 0x8; // Stack map table attribute
|
||||
int ATTR_STACK_MAP = 0x10; // Stack map attribute: cldc
|
||||
int ATTR_TYPE_ANNOTATION = 0x20; // type annotation attribute (jsr 308)
|
||||
int ATTR_METHOD_PARAMETERS = 0x40; // method parameters attribute (jep 118)
|
||||
|
||||
// See java.lang.invoke.LambdaMetafactory constants - option bitflags when calling altMetaFactory()
|
||||
int FLAG_SERIALIZABLE = 0x01;
|
||||
int FLAG_MARKERS = 0x02;
|
||||
int FLAG_BRIDGES = 0x04;
|
||||
}
|
||||
@@ -0,0 +1,473 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2013 IBM Corporation and others.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* IBM Corporation - added constant AccDefault
|
||||
* IBM Corporation - added constants AccBridge and AccVarargs for J2SE 1.5
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
/**
|
||||
* Utility class for decoding modifier flags in Java elements.
|
||||
* <p>
|
||||
* This class provides static methods only.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the numeric values of these flags match the ones for class files
|
||||
* as described in the Java Virtual Machine Specification (except for
|
||||
* {@link #AccDeprecated}, {@link #AccAnnotationDefault}, and {@link #AccDefaultMethod}).
|
||||
* </p>
|
||||
* <p>
|
||||
* The AST class <code>Modifier</code> provides
|
||||
* similar functionality as this class, only in the
|
||||
* <code>org.eclipse.jdt.core.dom</code> package.
|
||||
* </p>
|
||||
*
|
||||
* @see IMember#getFlags()
|
||||
* @noinstantiate This class is not intended to be instantiated by clients.
|
||||
*/
|
||||
public final class Flags {
|
||||
|
||||
/**
|
||||
* Constant representing the absence of any flag.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int AccDefault = ClassFileConstants.AccDefault;
|
||||
/**
|
||||
* Public access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccPublic = ClassFileConstants.AccPublic;
|
||||
/**
|
||||
* Private access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccPrivate = ClassFileConstants.AccPrivate;
|
||||
/**
|
||||
* Protected access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccProtected = ClassFileConstants.AccProtected;
|
||||
/**
|
||||
* Static access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccStatic = ClassFileConstants.AccStatic;
|
||||
/**
|
||||
* Final access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccFinal = ClassFileConstants.AccFinal;
|
||||
/**
|
||||
* Synchronized access flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccSynchronized = ClassFileConstants.AccSynchronized;
|
||||
/**
|
||||
* Volatile property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccVolatile = ClassFileConstants.AccVolatile;
|
||||
/**
|
||||
* Transient property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccTransient = ClassFileConstants.AccTransient;
|
||||
/**
|
||||
* Native property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccNative = ClassFileConstants.AccNative;
|
||||
/**
|
||||
* Interface property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccInterface = ClassFileConstants.AccInterface;
|
||||
/**
|
||||
* Abstract property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccAbstract = ClassFileConstants.AccAbstract;
|
||||
/**
|
||||
* Strictfp property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccStrictfp = ClassFileConstants.AccStrictfp;
|
||||
/**
|
||||
* Super property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccSuper = ClassFileConstants.AccSuper;
|
||||
/**
|
||||
* Synthetic property flag. See The Java Virtual Machine Specification for more details.
|
||||
* @since 2.0
|
||||
*/
|
||||
public static final int AccSynthetic = ClassFileConstants.AccSynthetic;
|
||||
|
||||
// /**
|
||||
// * Deprecated property flag.
|
||||
// * <p>
|
||||
// * Note that this flag's value is internal and is not defined in the
|
||||
// * Virtual Machine specification.
|
||||
// * </p>
|
||||
// * @since 2.0
|
||||
// */
|
||||
// public static final int AccDeprecated = ClassFileConstants.AccDeprecated;
|
||||
|
||||
/**
|
||||
* Bridge method property flag (added in J2SE 1.5). Used to flag a compiler-generated
|
||||
* bridge methods.
|
||||
* See The Java Virtual Machine Specification for more details.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int AccBridge = ClassFileConstants.AccBridge;
|
||||
|
||||
/**
|
||||
* Varargs method property flag (added in J2SE 1.5).
|
||||
* Used to flag variable arity method declarations.
|
||||
* See The Java Virtual Machine Specification for more details.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int AccVarargs = ClassFileConstants.AccVarargs;
|
||||
|
||||
/**
|
||||
* Enum property flag (added in J2SE 1.5).
|
||||
* See The Java Virtual Machine Specification for more details.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int AccEnum = ClassFileConstants.AccEnum;
|
||||
|
||||
/**
|
||||
* Annotation property flag (added in J2SE 1.5).
|
||||
* See The Java Virtual Machine Specification for more details.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final int AccAnnotation = ClassFileConstants.AccAnnotation;
|
||||
|
||||
// /**
|
||||
// * Default method property flag.
|
||||
// * <p>
|
||||
// * Note that this flag's value is internal and is not defined in the
|
||||
// * Virtual Machine specification.
|
||||
// * </p>
|
||||
// * @since 3.10
|
||||
// */
|
||||
// public static final int AccDefaultMethod = ExtraCompilerModifiers.AccDefaultMethod;
|
||||
//
|
||||
// /**
|
||||
// * Annotation method default property flag.
|
||||
// * Used to flag annotation type methods that declare a default value.
|
||||
// * <p>
|
||||
// * Note that this flag's value is internal and is not defined in the
|
||||
// * Virtual Machine specification.
|
||||
// * </p>
|
||||
// * @since 3.10
|
||||
// */
|
||||
// public static final int AccAnnotationDefault = ClassFileConstants.AccAnnotationDefault;
|
||||
|
||||
/**
|
||||
* Not instantiable.
|
||||
*/
|
||||
private Flags() {
|
||||
// Not instantiable
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>abstract</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>abstract</code> modifier is included
|
||||
*/
|
||||
public static boolean isAbstract(int flags) {
|
||||
return (flags & AccAbstract) != 0;
|
||||
}
|
||||
// /**
|
||||
// * Returns whether the given integer includes the indication that the
|
||||
// * element is deprecated (<code>@deprecated</code> tag in Javadoc comment).
|
||||
// *
|
||||
// * @param flags the flags
|
||||
// * @return <code>true</code> if the element is marked as deprecated
|
||||
// */
|
||||
// public static boolean isDeprecated(int flags) {
|
||||
// return (flags & AccDeprecated) != 0;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>final</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>final</code> modifier is included
|
||||
*/
|
||||
public static boolean isFinal(int flags) {
|
||||
return (flags & AccFinal) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>interface</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>interface</code> modifier is included
|
||||
* @since 2.0
|
||||
*/
|
||||
public static boolean isInterface(int flags) {
|
||||
return (flags & AccInterface) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>native</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>native</code> modifier is included
|
||||
*/
|
||||
public static boolean isNative(int flags) {
|
||||
return (flags & AccNative) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer does not include one of the
|
||||
* <code>public</code>, <code>private</code>, or <code>protected</code> flags.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if no visibility flag is set
|
||||
* @since 3.2
|
||||
*/
|
||||
public static boolean isPackageDefault(int flags) {
|
||||
return (flags & (AccPublic | AccPrivate | AccProtected)) == 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>private</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>private</code> modifier is included
|
||||
*/
|
||||
public static boolean isPrivate(int flags) {
|
||||
return (flags & AccPrivate) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>protected</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>protected</code> modifier is included
|
||||
*/
|
||||
public static boolean isProtected(int flags) {
|
||||
return (flags & AccProtected) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>public</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>public</code> modifier is included
|
||||
*/
|
||||
public static boolean isPublic(int flags) {
|
||||
return (flags & AccPublic) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>static</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>static</code> modifier is included
|
||||
*/
|
||||
public static boolean isStatic(int flags) {
|
||||
return (flags & AccStatic) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>super</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>super</code> modifier is included
|
||||
* @since 3.2
|
||||
*/
|
||||
public static boolean isSuper(int flags) {
|
||||
return (flags & AccSuper) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>strictfp</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>strictfp</code> modifier is included
|
||||
*/
|
||||
public static boolean isStrictfp(int flags) {
|
||||
return (flags & AccStrictfp) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>synchronized</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>synchronized</code> modifier is included
|
||||
*/
|
||||
public static boolean isSynchronized(int flags) {
|
||||
return (flags & AccSynchronized) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the indication that the
|
||||
* element is synthetic.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the element is marked synthetic
|
||||
*/
|
||||
public static boolean isSynthetic(int flags) {
|
||||
return (flags & AccSynthetic) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>transient</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>transient</code> modifier is included
|
||||
*/
|
||||
public static boolean isTransient(int flags) {
|
||||
return (flags & AccTransient) != 0;
|
||||
}
|
||||
/**
|
||||
* Returns whether the given integer includes the <code>volatile</code> modifier.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>volatile</code> modifier is included
|
||||
*/
|
||||
public static boolean isVolatile(int flags) {
|
||||
return (flags & AccVolatile) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given integer has the <code>AccBridge</code>
|
||||
* bit set.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>AccBridge</code> flag is included
|
||||
* @see #AccBridge
|
||||
* @since 3.0
|
||||
*/
|
||||
public static boolean isBridge(int flags) {
|
||||
return (flags & AccBridge) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given integer has the <code>AccVarargs</code>
|
||||
* bit set.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>AccVarargs</code> flag is included
|
||||
* @see #AccVarargs
|
||||
* @since 3.0
|
||||
*/
|
||||
public static boolean isVarargs(int flags) {
|
||||
return (flags & AccVarargs) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given integer has the <code>AccEnum</code>
|
||||
* bit set.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>AccEnum</code> flag is included
|
||||
* @see #AccEnum
|
||||
* @since 3.0
|
||||
*/
|
||||
public static boolean isEnum(int flags) {
|
||||
return (flags & AccEnum) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given integer has the <code>AccAnnotation</code>
|
||||
* bit set.
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return <code>true</code> if the <code>AccAnnotation</code> flag is included
|
||||
* @see #AccAnnotation
|
||||
* @since 3.0
|
||||
*/
|
||||
public static boolean isAnnotation(int flags) {
|
||||
return (flags & AccAnnotation) != 0;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns whether the given integer has the <code>AccDefaultMethod</code>
|
||||
// * bit set. Note that this flag represents the usage of the 'default' keyword
|
||||
// * on a method and should not be confused with the 'package' access visibility (which used to be called 'default access').
|
||||
// *
|
||||
// * @return <code>true</code> if the <code>AccDefaultMethod</code> flag is included
|
||||
// * @see #AccDefaultMethod
|
||||
// * @since 3.10
|
||||
// */
|
||||
// public static boolean isDefaultMethod(int flags) {
|
||||
// return (flags & AccDefaultMethod) != 0;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Returns whether the given integer has the <code>AccAnnnotationDefault</code>
|
||||
// * bit set.
|
||||
// *
|
||||
// * @return <code>true</code> if the <code>AccAnnotationDefault</code> flag is included
|
||||
// * @see #AccAnnotationDefault
|
||||
// * @since 3.10
|
||||
// */
|
||||
// public static boolean isAnnnotationDefault(int flags) {
|
||||
// return (flags & AccAnnotationDefault) != 0;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns a standard string describing the given modifier flags.
|
||||
* Only modifier flags are included in the output; deprecated,
|
||||
* synthetic, bridge, etc. flags are ignored.
|
||||
* <p>
|
||||
* The flags are output in the following order:
|
||||
* <pre> public protected private
|
||||
* abstract default static final synchronized native strictfp transient volatile</pre>
|
||||
* <p>
|
||||
* This order is consistent with the recommendations in JLS8 ("*Modifier:" rules in chapters 8 and 9).
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the flags of a method can include the AccVarargs flag that has no standard description. Since the AccVarargs flag has the same value as
|
||||
* the AccTransient flag (valid for fields only), attempting to get the description of method modifiers with the AccVarargs flag set would result in an
|
||||
* unexpected description. Clients should ensure that the AccVarargs is not included in the flags of a method as follows:
|
||||
* <pre>
|
||||
* IMethod method = ...
|
||||
* int flags = method.getFlags() & ~Flags.AccVarargs;
|
||||
* return Flags.toString(flags);
|
||||
* </pre>
|
||||
* </p>
|
||||
* <p>
|
||||
* Examples results:
|
||||
* <pre>
|
||||
* <code>"public static final"</code>
|
||||
* <code>"private native"</code>
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @param flags the flags
|
||||
* @return the standard string representation of the given flags
|
||||
*/
|
||||
public static String toString(int flags) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
if (isPublic(flags))
|
||||
sb.append("public "); //$NON-NLS-1$
|
||||
if (isProtected(flags))
|
||||
sb.append("protected "); //$NON-NLS-1$
|
||||
if (isPrivate(flags))
|
||||
sb.append("private "); //$NON-NLS-1$
|
||||
if (isAbstract(flags))
|
||||
sb.append("abstract "); //$NON-NLS-1$
|
||||
// if (isDefaultMethod(flags))
|
||||
// sb.append("default "); //$NON-NLS-1$
|
||||
if (isStatic(flags))
|
||||
sb.append("static "); //$NON-NLS-1$
|
||||
if (isFinal(flags))
|
||||
sb.append("final "); //$NON-NLS-1$
|
||||
if (isSynchronized(flags))
|
||||
sb.append("synchronized "); //$NON-NLS-1$
|
||||
if (isNative(flags))
|
||||
sb.append("native "); //$NON-NLS-1$
|
||||
if (isStrictfp(flags))
|
||||
sb.append("strictfp "); //$NON-NLS-1$
|
||||
if (isTransient(flags))
|
||||
sb.append("transient "); //$NON-NLS-1$
|
||||
if (isVolatile(flags))
|
||||
sb.append("volatile "); //$NON-NLS-1$
|
||||
int len = sb.length();
|
||||
if (len == 0)
|
||||
return ""; //$NON-NLS-1$
|
||||
sb.setLength(len - 1);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface IAnnotatable extends IJavaElement {
|
||||
|
||||
IAnnotation[] getAnnotations();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface IAnnotation extends IJavaElement {
|
||||
|
||||
/**
|
||||
* Returns the member-value pairs of this annotation. Returns an empty
|
||||
* array if this annotation is a marker annotation. Returns a size-1 array if this
|
||||
* annotation is a single member annotation. In this case, the member
|
||||
* name is always <code>"value"</code>.
|
||||
*
|
||||
* @return the member-value pairs of this annotation
|
||||
*/
|
||||
IMemberValuePair[] getMemberValuePairs();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface IField extends IMember {
|
||||
boolean isEnumConstant();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
|
||||
public interface IJavaElement {
|
||||
String getElementName();
|
||||
HtmlSnippet getJavaDoc();
|
||||
boolean exists();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public interface IJavaProject extends IJavaElement {
|
||||
IType findType(String fqName);
|
||||
Path getPath();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface IMember extends IJavaElement, IAnnotatable {
|
||||
|
||||
/**
|
||||
* Returns the modifier flags for this member. The flags can be examined using class
|
||||
* <code>Flags</code>.
|
||||
* <p>
|
||||
* For {@linkplain #isBinary() binary} members, flags from the class file
|
||||
* as well as derived flags {@link Flags#AccAnnotationDefault} and {@link Flags#AccDefaultMethod} are included.
|
||||
* </p>
|
||||
* <p>
|
||||
* For source members, only flags as indicated in the source are returned. Thus if an interface
|
||||
* defines a method <code>void myMethod();</code>, the flags don't include the
|
||||
* 'public' flag. Source flags include {@link Flags#AccAnnotationDefault} as well.
|
||||
* </p>
|
||||
*
|
||||
* @exception JavaModelException if this element does not exist or if an
|
||||
* exception occurs while accessing its corresponding resource.
|
||||
* @return the modifier flags for this member
|
||||
* @see Flags
|
||||
*/
|
||||
int getFlags();
|
||||
|
||||
/**
|
||||
* Returns the type in which this member is declared, or <code>null</code>
|
||||
* if this member is not declared in a type (for example, a top-level type).
|
||||
* This is a handle-only method.
|
||||
*
|
||||
* @return the type in which this member is declared, or <code>null</code>
|
||||
* if this member is not declared in a type (for example, a top-level type)
|
||||
*/
|
||||
IType getDeclaringType();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
public interface IMemberValuePair {
|
||||
|
||||
/**
|
||||
* Returns the member's name of this member-value pair.
|
||||
*
|
||||
* @return the member's name of this member-value pair.
|
||||
*/
|
||||
String getMemberName();
|
||||
|
||||
/**
|
||||
* Returns the value of this member-value pair. The type of this value
|
||||
* is function of this member-value pair's {@link #getValueKind() value kind}. It is an
|
||||
* instance of {@link Object}[] if the value is an array.
|
||||
* <p>
|
||||
* If the value kind is {@link #K_UNKNOWN} and the value is not an array, then the
|
||||
* value is <code>null</code>.
|
||||
* If the value kind is {@link #K_UNKNOWN} and the value is an array, then the
|
||||
* value is an array containing {@link Object}s and/or <code>null</code>s for
|
||||
* unknown elements.
|
||||
* See {@link #K_UNKNOWN} for more details.
|
||||
* </p>
|
||||
* @return the value of this member-value pair.
|
||||
*/
|
||||
Object getValue();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
import org.springframework.ide.vscode.boot.properties.metadata.types.Signature;
|
||||
|
||||
public interface IMethod extends IMember {
|
||||
|
||||
/**
|
||||
* Returns the type signature of the return value of this method.
|
||||
* For constructors, this returns the signature for void.
|
||||
* <p>
|
||||
* For example, a source method declared as <code>public String getName()</code>
|
||||
* would return <code>"QString;"</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* The type signature may be either unresolved (for source types)
|
||||
* or resolved (for binary types), and either basic (for basic types)
|
||||
* or rich (for parameterized types). See {@link Signature} for details.
|
||||
* </p>
|
||||
*
|
||||
* @exception JavaModelException if this element does not exist or if an
|
||||
* exception occurs while accessing its corresponding resource.
|
||||
* @return the type signature of the return value of this method, void for constructors
|
||||
* @see Signature
|
||||
*/
|
||||
String getReturnType();
|
||||
|
||||
/**
|
||||
* Returns the signature of this method. This includes the signatures for the
|
||||
* parameter types and return type, but does not include the method name,
|
||||
* exception types, or type parameters.
|
||||
* <p>
|
||||
* For example, a source method declared as <code>public void foo(String text, int length)</code>
|
||||
* would return <code>"(QString;I)V"</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* The type signatures embedded in the method signature may be either unresolved
|
||||
* (for source types) or resolved (for binary types), and either basic (for
|
||||
* basic types) or rich (for parameterized types). See {@link Signature} for
|
||||
* details.
|
||||
* </p>
|
||||
*
|
||||
* @return the signature of this method
|
||||
* @exception JavaModelException if this element does not exist or if an
|
||||
* exception occurs while accessing its corresponding resource.
|
||||
* @see Signature
|
||||
*/
|
||||
String getSignature();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2015 IBM Corporation and others.
|
||||
* 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:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* IBM Corporation - added J2SE 1.5 support
|
||||
* Stephan Herrmann - Contribution for
|
||||
* Bug 463533 - Signature.getSignatureSimpleName() returns different results for resolved and unresolved extends
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.java;
|
||||
|
||||
/**
|
||||
* Replaces eclipse JDT IType.
|
||||
*/
|
||||
public interface IType extends IMember {
|
||||
|
||||
boolean isClass();
|
||||
boolean isEnum();
|
||||
boolean isInterface();
|
||||
|
||||
/**
|
||||
* Returns the fully qualified name of this type,
|
||||
* including qualification for any containing types and packages.
|
||||
* This is the name of the package, followed by <code>'.'</code>,
|
||||
* followed by the type-qualified name.
|
||||
* <p>
|
||||
* <b>Note</b>: The enclosing type separator used in the type-qualified
|
||||
* name is <code>'$'</code>, not <code>'.'</code>.
|
||||
* </p>
|
||||
* This method is fully equivalent to <code>getFullyQualifiedName('$')</code>.
|
||||
* This is a handle-only method.
|
||||
*
|
||||
* @see IType#getTypeQualifiedName()
|
||||
* @see IType#getFullyQualifiedName(char)
|
||||
* @return the fully qualified name of this type
|
||||
*/
|
||||
String getFullyQualifiedName();
|
||||
|
||||
/**
|
||||
* Returns the field with the specified name
|
||||
* in this type (for example, <code>"bar"</code>).
|
||||
* This is a handle-only method. The field may or may not exist.
|
||||
*
|
||||
* @param name the given name
|
||||
* @return the field with the specified name in this type
|
||||
*/
|
||||
IField getField(String name);
|
||||
|
||||
/**
|
||||
* Returns the fields declared by this type in the order in which they appear
|
||||
* in the source or class file. For binary types, this includes synthetic fields.
|
||||
*
|
||||
* @return the fields declared by this type
|
||||
*/
|
||||
IField[] getFields();
|
||||
|
||||
/**
|
||||
* Returns the method with the specified name and parameter types
|
||||
* in this type (for example, <code>"foo", {"I", "QString;"}</code>).
|
||||
* To get the handle for a constructor, the name specified must be the
|
||||
* simple name of the enclosing type.
|
||||
* This is a handle-only method. The method may or may not be present.
|
||||
* <p>
|
||||
* The type signatures may be either unresolved (for source types)
|
||||
* or resolved (for binary types), and either basic (for basic types)
|
||||
* or rich (for parameterized types). See {@link Signature} for details.
|
||||
* Note that the parameter type signatures for binary methods are expected
|
||||
* to be dot-based.
|
||||
* </p>
|
||||
*
|
||||
* @param name the given name
|
||||
* @param parameterTypeSignatures the given parameter types
|
||||
* @return the method with the specified name and parameter types in this type
|
||||
*/
|
||||
IMethod getMethod(String name, String[] parameterTypeSignatures);
|
||||
|
||||
/**
|
||||
* Returns the methods and constructors declared by this type.
|
||||
* For binary types, this may include the special <code><clinit></code> method
|
||||
* and synthetic methods.
|
||||
* <p>
|
||||
* The results are listed in the order in which they appear in the source or class file.
|
||||
* </p>
|
||||
*
|
||||
* @return the methods and constructors declared by this type
|
||||
*/
|
||||
IMethod[] getMethods();
|
||||
|
||||
/**
|
||||
* Resolves the given type name within the context of this type (depending on the type hierarchy
|
||||
* and its imports).
|
||||
* <p>
|
||||
* Multiple answers might be found in case there are ambiguous matches.
|
||||
* </p>
|
||||
* <p>
|
||||
* Each matching type name is decomposed as an array of two strings, the first denoting the package
|
||||
* name (dot-separated) and the second being the type name. The package name is empty if it is the
|
||||
* default package. The type name is the type qualified name using a '.' enclosing type separator.
|
||||
* </p>
|
||||
* <p>
|
||||
* Returns <code>null</code> if unable to find any matching type.
|
||||
* </p>
|
||||
*<p>
|
||||
* For example, resolution of <code>"Object"</code> would typically return
|
||||
* <code>{{"java.lang", "Object"}}</code>. Another resolution that returns
|
||||
* <code>{{"", "X.Inner"}}</code> represents the inner type Inner defined in type X in the
|
||||
* default package.
|
||||
* </p>
|
||||
*
|
||||
* @param typeName the given type name
|
||||
* @return the resolved type names or <code>null</code> if unable to find any matching type
|
||||
* @see #getTypeQualifiedName(char)
|
||||
*/
|
||||
String[][] resolveType(String typeName);
|
||||
|
||||
}
|
||||
@@ -12,30 +12,16 @@
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<!-- Sonatype snapshots repository -->
|
||||
<repository>
|
||||
<id>oss-sonatype</id>
|
||||
<name>oss-sonatype</name>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>language-server-test-harness</artifactId>
|
||||
<artifactId>commons-java</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Java implementation of VS Code language server protocol -->
|
||||
<dependency>
|
||||
@@ -79,5 +65,15 @@
|
||||
<artifactId>jackson-datatype-jdk8</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>language-server-test-harness</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
<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>
|
||||
<artifactId>language-server-commons</artifactId>
|
||||
<name>language-server-commons</name>
|
||||
<description>Shared utilities for building vscode language servers in Java</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<repositories>
|
||||
<!-- Sonatype snapshots repository -->
|
||||
<repository>
|
||||
<id>oss-sonatype</id>
|
||||
<name>oss-sonatype</name>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>commons-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!-- testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>language-server-test-harness</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Java implementation of VS Code language server protocol -->
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi.services</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.typefox.lsapi</groupId>
|
||||
<artifactId>io.typefox.lsapi.annotations</artifactId>
|
||||
<version>${lsapi-version}</version>
|
||||
</dependency>
|
||||
<!-- JSON -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jdk8</artifactId>
|
||||
<version>${jackson-2-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -8,15 +8,15 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.completion;
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.Region;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.Region;
|
||||
|
||||
import io.typefox.lsapi.TextEdit;
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.completion;
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.commons.completion;
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
import io.typefox.lsapi.CompletionItemKind;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.completion;
|
||||
package org.springframework.ide.vscode.commons.languageserver.completion;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
|
||||
/**
|
||||
* Interface that represents the methods that one needs to implement in order
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.springframework.ide.vscode.commons.languageserver.java;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.java.IType;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
|
||||
public class DefaultJavaProjectFinder implements JavaProjectFinder {
|
||||
|
||||
private final String CLASSPATH_FILE_NAME;
|
||||
|
||||
public DefaultJavaProjectFinder(String classpathFileName) {
|
||||
this.CLASSPATH_FILE_NAME = classpathFileName;
|
||||
}
|
||||
|
||||
private File findClasspathFile(File file) {
|
||||
if (file!=null && file.exists()) {
|
||||
File cpFile = new File(file, CLASSPATH_FILE_NAME);
|
||||
if (cpFile.isFile()) {
|
||||
return cpFile;
|
||||
} else {
|
||||
return findClasspathFile(file.getParentFile());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IJavaProject find(IDocument d) {
|
||||
String uriStr = d.getUri();
|
||||
if (StringUtil.hasText(uriStr)) {
|
||||
try {
|
||||
URI uri = new URI(uriStr);
|
||||
//TODO: This only work with File uri. Should it work with others too?
|
||||
File file = new File(uri).getAbsoluteFile();
|
||||
File cpFile = findClasspathFile(file);
|
||||
if (cpFile!=null) {
|
||||
return new JavaProjectWithClasspathFile(cpFile);
|
||||
}
|
||||
} catch (URISyntaxException | IllegalArgumentException e) {
|
||||
//garbage data. Ignore it.
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
private static class JavaProjectWithClasspathFile implements IJavaProject {
|
||||
|
||||
private File cpFile;
|
||||
|
||||
public JavaProjectWithClasspathFile(File cpFile) {
|
||||
this.cpFile = cpFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return cpFile.getParentFile().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HtmlSnippet getJavaDoc() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists() {
|
||||
return cpFile.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IType findType(String fqName) {
|
||||
//TODO: implement
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getPath() {
|
||||
return cpFile.getParentFile().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JavaProjectWithClasspathFile("+cpFile+")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.springframework.ide.vscode.commons.languageserver.java;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.java.IJavaProject;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface JavaProjectFinder {
|
||||
JavaProjectFinder DEFAULT = new DefaultJavaProjectFinder("classpath.txt");
|
||||
IJavaProject find(IDocument doc);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.commons.languageserver.quickfix;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
|
||||
/**
|
||||
* Represents a strategy for computing potential quickfixes for a given problem.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ProblemFixer {
|
||||
|
||||
/**
|
||||
* Implementor can inspect the problem and quickfix context provided as parameters.
|
||||
* <p>
|
||||
* If the problem is deemed fixable, the strategy can contribute one or more fixes by
|
||||
* adding them to the list of proposals (provided as third parameter).
|
||||
*/
|
||||
void contributeFixes(
|
||||
QuickfixContext context, ReconcileProblem problem,
|
||||
List<ICompletionProposal> proposals
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015, 2016 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.commons.languageserver.quickfix;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
/**
|
||||
* Provides access to additional context info and objects that quickfixes might
|
||||
* need in order to be able to apply themselves.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public interface QuickfixContext {
|
||||
// IProject getProject();
|
||||
// IPreferenceStore getWorkspacePreferences();
|
||||
// IPreferenceStore getProjectPreferences();
|
||||
// IJavaProject getJavaProject();
|
||||
// UserInteractions getUI();
|
||||
IDocument getDocument();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
/**
|
||||
* A fake reconcule engine which is not useful except for quickly testing
|
||||
* whether stuff is wired up correctly to the editor.
|
||||
*/
|
||||
public class BadWordReconcileEngine implements IReconcileEngine {
|
||||
|
||||
static enum BWProblemType implements ProblemType {
|
||||
VERY_BAD_WORD,
|
||||
BAD_WORD;
|
||||
|
||||
@Override
|
||||
public ProblemSeverity getDefaultSeverity() {
|
||||
if (this==VERY_BAD_WORD) {
|
||||
return ProblemSeverity.ERROR;
|
||||
} else {
|
||||
return ProblemSeverity.WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return this.name();
|
||||
}
|
||||
}
|
||||
|
||||
private final String[] BADWORDS = {
|
||||
"bar", "foo"
|
||||
};
|
||||
|
||||
public BadWordReconcileEngine() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reconcile(IDocument doc, IProblemCollector problemCollector) {
|
||||
String text = doc.get();
|
||||
System.out.println(">>>> reconciling for bad words ==========");
|
||||
System.out.println(text);
|
||||
System.out.println("<<<< reconciling for bad words ==========");
|
||||
|
||||
problemCollector.beginCollecting();
|
||||
try {
|
||||
for (String badword : BADWORDS) {
|
||||
int pos = 0;
|
||||
while (pos>=0 && pos < text.length()) {
|
||||
int badPos = text.indexOf(badword, pos);
|
||||
if (badPos>=0) {
|
||||
if (badword.equals(BADWORDS[0])) {
|
||||
problemCollector.accept(new ReconcileProblemImpl(BWProblemType.VERY_BAD_WORD, "'"+badword+"' is a VERY bad word", badPos, badword.length()));
|
||||
} else {
|
||||
problemCollector.accept(new ReconcileProblemImpl(BWProblemType.BAD_WORD, "'"+badword+"' is a bad word", badPos, badword.length()));
|
||||
}
|
||||
pos = badPos+1;
|
||||
} else {
|
||||
pos = badPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
problemCollector.endCollecting();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
public interface IProblemCollector {
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
public interface IReconcileEngine {
|
||||
public void reconcile(IDocument doc, IProblemCollector problemCollector);
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
/**
|
||||
* Besides the methods below, the only hard requirement for a 'problem type' is
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
/**
|
||||
* Minamal interface that objects representing a reconciler problem must
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.commons.reconcile;
|
||||
package org.springframework.ide.vscode.commons.languageserver.reconcile;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ReconcileProblem} that is just a simple data object.
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
/**
|
||||
* Replacement for Eclipse's BadLocationException (so as ot make porting code easier)
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
|
||||
public class DocumentUtil {
|
||||
|
||||
//TODO: this stuff belongs in IDocument and its implementation, not here. This class should be removed.
|
||||
|
||||
/**
|
||||
* Fetch text between two offsets. Doesn't throw BadLocationException.
|
||||
* If either one or both of the offsets points outside the
|
||||
@@ -1,7 +1,8 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
public interface IDocument {
|
||||
|
||||
String getUri();
|
||||
String get();
|
||||
IRegion getLineInformationOfOffset(int offset);
|
||||
int getLength();
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
/**
|
||||
* Mimicks eclipse IRegion (i.e. a region is a offset + length).
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
public abstract class PrefixFinder {
|
||||
public String getPrefix(IDocument doc, int offset, int lowerBound) {
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
/**
|
||||
* Trivial implementation of {@link IRegion}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import io.typefox.lsapi.MessageParams;
|
||||
import io.typefox.lsapi.impl.MessageParamsImpl;
|
||||
@@ -1,17 +1,26 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
|
||||
import io.typefox.lsapi.DiagnosticSeverity;
|
||||
import io.typefox.lsapi.InitializeParams;
|
||||
import io.typefox.lsapi.InitializeResult;
|
||||
import io.typefox.lsapi.MessageParams;
|
||||
import io.typefox.lsapi.MessageType;
|
||||
import io.typefox.lsapi.ShowMessageRequestParams;
|
||||
import io.typefox.lsapi.impl.DiagnosticImpl;
|
||||
import io.typefox.lsapi.impl.InitializeResultImpl;
|
||||
import io.typefox.lsapi.impl.MessageParamsImpl;
|
||||
import io.typefox.lsapi.impl.ServerCapabilitiesImpl;
|
||||
@@ -134,5 +143,54 @@ public abstract class SimpleLanguageServer implements LanguageServer {
|
||||
//TODO: not sure what this is for exactly. We just stub it and do nothing for now.
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method. Subclasses can call this to use a {@link IReconcileEngine} ported
|
||||
* from old STS codebase to validate a given {@link TextDocument} and publish Diagnostics.
|
||||
*/
|
||||
protected void validateWith(TextDocument doc, IReconcileEngine engine) {
|
||||
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
IProblemCollector problems = new IProblemCollector() {
|
||||
|
||||
private List<DiagnosticImpl> diagnostics = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void endCollecting() {
|
||||
documents.publishDiagnostics(doc, diagnostics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginCollecting() {
|
||||
diagnostics.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ReconcileProblem problem) {
|
||||
DiagnosticSeverity severity = getDiagnosticSeverity(problem);
|
||||
if (severity!=null) {
|
||||
DiagnosticImpl d = new DiagnosticImpl();
|
||||
d.setCode(problem.getCode());
|
||||
d.setMessage(problem.getMessage());
|
||||
d.setRange(doc.toRange(problem.getOffset(), problem.getLength()));
|
||||
d.setSeverity(severity);
|
||||
diagnostics.add(d);
|
||||
}
|
||||
}
|
||||
|
||||
private DiagnosticSeverity getDiagnosticSeverity(ReconcileProblem problem) {
|
||||
ProblemSeverity severity = problem.getType().getDefaultSeverity();
|
||||
switch (severity) {
|
||||
case ERROR:
|
||||
return DiagnosticSeverity.Error;
|
||||
case WARNING:
|
||||
return DiagnosticSeverity.Warning;
|
||||
case IGNORE:
|
||||
return null;
|
||||
default:
|
||||
throw new IllegalStateException("Bug! Missing switch case?");
|
||||
}
|
||||
}
|
||||
};
|
||||
engine.reconcile(doc, problems);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -10,6 +10,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.Futures;
|
||||
|
||||
import io.typefox.lsapi.CodeActionParams;
|
||||
import io.typefox.lsapi.CodeLens;
|
||||
import io.typefox.lsapi.CodeLensParams;
|
||||
@@ -44,16 +47,16 @@ import io.typefox.lsapi.impl.PublishDiagnosticsParamsImpl;
|
||||
import io.typefox.lsapi.services.TextDocumentService;
|
||||
|
||||
public class SimpleTextDocumentService implements TextDocumentService {
|
||||
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(SimpleTextDocumentService.class.getName());
|
||||
|
||||
|
||||
private Consumer<PublishDiagnosticsParams> publishDiagnostics = (p) -> {};
|
||||
|
||||
|
||||
private Map<String, TextDocument> documents = new HashMap<>();
|
||||
private ListenerList<TextDocumentContentChange> documentChangeListeners = new ListenerList<>();
|
||||
private CompletionHandler completionHandler = null;
|
||||
private CompletionResolveHandler completionResolveHandler = null;
|
||||
|
||||
|
||||
public synchronized void onCompletion(CompletionHandler h) {
|
||||
Assert.isNull("A completion handler is already set, multiple handlers not supported yet", completionHandler);
|
||||
this.completionHandler = h;
|
||||
@@ -85,7 +88,7 @@ public class SimpleTextDocumentService implements TextDocumentService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void didOpen(DidOpenTextDocumentParams params) {
|
||||
//LOG.info("didOpen: "+params);
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -11,7 +11,7 @@ import io.typefox.lsapi.WorkspaceSymbolParams;
|
||||
import io.typefox.lsapi.services.WorkspaceService;
|
||||
|
||||
public class SimpleWorkspaceService implements WorkspaceService {
|
||||
|
||||
|
||||
private ListenerList<Settings> configurationListeners = new ListenerList<>();
|
||||
|
||||
@Override
|
||||
@@ -34,5 +34,5 @@ public class SimpleWorkspaceService implements WorkspaceService {
|
||||
public void onDidChangeConfiguraton(Consumer<Settings> l) {
|
||||
configurationListeners.add(l);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
|
||||
import io.typefox.lsapi.TextDocumentContentChangeEvent;
|
||||
|
||||
@@ -15,11 +15,12 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
|
||||
import org.springframework.ide.vscode.testharness.Editor;
|
||||
import org.springframework.ide.vscode.testharness.LanguageServerHarness;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.TextDocument;
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
|
||||
@@ -10,4 +10,17 @@
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2015 Pivotal, Inc.
|
||||
* Copyright (c) 2014-2015 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
|
||||
@@ -8,17 +8,25 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.properties.util;
|
||||
|
||||
import java.util.Collection;
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
/**
|
||||
* Parser that always fails, regardless of the input. Used for types who's value cannot be
|
||||
* expressed as a 'scalar' string value.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class CollectionUtil {
|
||||
public class AlwaysFailingParser implements ValueParser {
|
||||
|
||||
public static <E> boolean hasElements(Collection<E> c) {
|
||||
return c!=null && !c.isEmpty();
|
||||
private String typeName;
|
||||
|
||||
public AlwaysFailingParser(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parse(String str) {
|
||||
throw new IllegalArgumentException("'"+str+"' is not valid for type '"+typeName+"'");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.properties.util;
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.util;
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
@@ -0,0 +1,171 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2014-2016 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.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
/**
|
||||
* Helper class to make it a little easier to create simple html page.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class HtmlBuffer {
|
||||
|
||||
private StringBuffer buffer = new StringBuffer();
|
||||
private boolean epilogAdded = false; //to ensure only added once.
|
||||
|
||||
public HtmlBuffer() {
|
||||
this.buffer = new StringBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text, applies escaping to the text as needed.
|
||||
*/
|
||||
public void text(String text) {
|
||||
raw(convertToHTMLContent(text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append 'raw' text. Doesn't apply any escaping.
|
||||
*/
|
||||
public void raw(String rawText) {
|
||||
if (epilogAdded) {
|
||||
throw new IllegalStateException("Can not append more text after epilog was added");
|
||||
}
|
||||
buffer.append(rawText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text, applies urlencoding to the text.
|
||||
*/
|
||||
public void url(String string) {
|
||||
try {
|
||||
raw(URLEncoder.encode(string, "utf8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
if (!epilogAdded && buffer.length()>0) {
|
||||
epilogAdded = true;
|
||||
addPrologAndEpilog();
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected void addPrologAndEpilog() {
|
||||
// HTMLPrinter.insertPageProlog(buffer, 0, getCSSStyles());
|
||||
// HTMLPrinter.addPageEpilog(buffer);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Note: copied from org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getCSSStyles()
|
||||
// * Returns the style information for displaying HTML (Javadoc) content.
|
||||
// *
|
||||
// * @return the CSS styles
|
||||
// * @since 3.3
|
||||
// */
|
||||
// public static String getCSSStyles() {
|
||||
// if (fgCSSStyles == null) {
|
||||
// Bundle bundle= Platform.getBundle(JavaPlugin.getPluginId());
|
||||
// URL url= bundle.getEntry("/JavadocHoverStyleSheet.css"); //$NON-NLS-1$
|
||||
// if (url != null) {
|
||||
// BufferedReader reader= null;
|
||||
// try {
|
||||
// url= FileLocator.toFileURL(url);
|
||||
// reader= new BufferedReader(new InputStreamReader(url.openStream()));
|
||||
// StringBuffer buffer= new StringBuffer(200);
|
||||
// String line= reader.readLine();
|
||||
// while (line != null) {
|
||||
// buffer.append(line);
|
||||
// buffer.append('\n');
|
||||
// line= reader.readLine();
|
||||
// }
|
||||
// fgCSSStyles= buffer.toString();
|
||||
// } catch (IOException ex) {
|
||||
// JavaPlugin.log(ex);
|
||||
// } finally {
|
||||
// try {
|
||||
// if (reader != null)
|
||||
// reader.close();
|
||||
// } catch (IOException e) {
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// String css= fgCSSStyles;
|
||||
// if (css != null) {
|
||||
// FontData fontData= JFaceResources.getFontRegistry().getFontData(PreferenceConstants.APPEARANCE_JAVADOC_FONT)[0];
|
||||
// css= HTMLPrinter.convertTopLevelFont(css, fontData);
|
||||
// }
|
||||
// return css;
|
||||
// }
|
||||
|
||||
public void hline() {
|
||||
raw("<hr>");
|
||||
}
|
||||
|
||||
public void p(String string) {
|
||||
raw("<p>");
|
||||
text(string);
|
||||
raw("</p>");
|
||||
}
|
||||
|
||||
public void snippet(HtmlSnippet snippet) {
|
||||
snippet.render(this);
|
||||
}
|
||||
|
||||
public void bold(String string) {
|
||||
raw("<b>");
|
||||
text(string);
|
||||
raw("</b>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes reserved HTML characters in the given string.
|
||||
* <p>
|
||||
* <b>Warning:</b> Does not preserve whitespace.
|
||||
*
|
||||
* @param content the input string
|
||||
* @return the string with escaped characters
|
||||
*/
|
||||
public static String convertToHTMLContent(String content) {
|
||||
content= replace(content, '&', "&"); //$NON-NLS-1$
|
||||
content= replace(content, '"', """); //$NON-NLS-1$
|
||||
content= replace(content, '<', "<"); //$NON-NLS-1$
|
||||
return replace(content, '>', ">"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private static String replace(String text, char c, String s) {
|
||||
|
||||
int previous= 0;
|
||||
int current= text.indexOf(c, previous);
|
||||
|
||||
if (current == -1)
|
||||
return text;
|
||||
|
||||
StringBuffer buffer= new StringBuffer();
|
||||
while (current > -1) {
|
||||
buffer.append(text.substring(previous, current));
|
||||
buffer.append(s);
|
||||
previous= current + 1;
|
||||
current= text.indexOf(c, previous);
|
||||
}
|
||||
buffer.append(text.substring(previous));
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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.util;
|
||||
|
||||
/**
|
||||
* A snippet that can be rendered into html.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public abstract class HtmlSnippet {
|
||||
public abstract void render(HtmlBuffer html);
|
||||
|
||||
public String toHtml() {
|
||||
HtmlBuffer buf = new HtmlBuffer();
|
||||
render(buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
// Create snippets:
|
||||
|
||||
public static HtmlSnippet text(final String text) {
|
||||
return new HtmlSnippet() {
|
||||
@Override
|
||||
public void render(HtmlBuffer html) {
|
||||
html.text(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static HtmlSnippet raw(final String rawHtml) {
|
||||
return new HtmlSnippet() {
|
||||
@Override
|
||||
public void render(HtmlBuffer html) {
|
||||
html.raw(rawHtml);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static HtmlSnippet italic(String text) {
|
||||
return italic(text(text));
|
||||
}
|
||||
|
||||
public static HtmlSnippet italic(final HtmlSnippet wrappee) {
|
||||
return new HtmlSnippet() {
|
||||
@Override
|
||||
public void render(HtmlBuffer html) {
|
||||
html.raw("<i>");
|
||||
wrappee.render(html);
|
||||
html.raw("</i>");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// add more as needed ...
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
/**
|
||||
* An abstract class implementing {@link Provider}. The provided value
|
||||
* is computed on demand and cached once computed.
|
||||
* <p>
|
||||
* Subclass must implement the compute method.
|
||||
*/
|
||||
public abstract class LazyProvider<T> implements Provider<T> {
|
||||
|
||||
private boolean computed = false;
|
||||
private T cached = null;
|
||||
|
||||
@Override
|
||||
public synchronized final T get() {
|
||||
if (!computed) {
|
||||
cached = compute();
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
protected abstract T compute();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Deprecated, this class is here to make porting old STS code easier. Code should
|
||||
* avoid using this as much as possible and replaces calls to this by using Slf4J loggers
|
||||
* directly.
|
||||
*/
|
||||
@Deprecated
|
||||
public class Log {
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(Log.class);
|
||||
|
||||
public static void log(Throwable e) {
|
||||
logger.error("Error", e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.util;
|
||||
package org.springframework.ide.vscode.util;
|
||||
|
||||
/**
|
||||
* A ValueParser provides the means to Strings into some kind of
|
||||
@@ -26,12 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.17</version>
|
||||
<version>${yaml-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.springframework.ide.vscode.yaml.ast;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface YamlASTProvider {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package org.springframework.ide.vscode.cloudfoundry.manifest.editor;
|
||||
package org.springframework.ide.vscode.yaml.ast;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlASTProvider;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
public class YamlParser implements YamlASTProvider {
|
||||
@@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.completion;
|
||||
|
||||
import org.springframework.ide.vscode.util.PrefixFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.PrefixFinder;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SDocNode;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.springframework.ide.vscode.yaml.completion;
|
||||
|
||||
import org.springframework.ide.vscode.commons.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypedProperty;
|
||||
|
||||
@@ -2,9 +2,9 @@ package org.springframework.ide.vscode.yaml.completion;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.springframework.ide.vscode.commons.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypedProperty;
|
||||
|
||||
@@ -13,7 +13,7 @@ package org.springframework.ide.vscode.yaml.completion;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPathSegment;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SNode;
|
||||
|
||||
@@ -20,8 +20,8 @@ import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.util.FuzzyMatcher;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPath;
|
||||
|
||||
@@ -12,7 +12,7 @@ package org.springframework.ide.vscode.yaml.completion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlNavigable;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SNode;
|
||||
|
||||
@@ -15,10 +15,10 @@ import java.util.Collections;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionEngine;
|
||||
import org.springframework.ide.vscode.commons.completion.ICompletionProposal;
|
||||
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.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlDocument;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SKeyNode;
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.completion;
|
||||
|
||||
import org.springframework.ide.vscode.commons.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPathSegment;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPathSegment.YamlPathSegmentType;
|
||||
|
||||
@@ -4,16 +4,16 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ide.vscode.commons.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
import org.springframework.ide.vscode.util.ValueParser;
|
||||
import org.springframework.ide.vscode.yaml.ast.NodeUtil;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlFileAST;
|
||||
import org.springframework.ide.vscode.yaml.schema.YType;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypeUtil;
|
||||
import org.springframework.ide.vscode.yaml.schema.YTypedProperty;
|
||||
import org.springframework.ide.vscode.yaml.schema.YamlSchema;
|
||||
import org.springframework.ide.vscode.yaml.util.ValueParser;
|
||||
import org.yaml.snakeyaml.nodes.MappingNode;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.NodeTuple;
|
||||
|
||||
@@ -2,10 +2,10 @@ package org.springframework.ide.vscode.yaml.reconcile;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.reconcile.IReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlASTProvider;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlFileAST;
|
||||
import org.yaml.snakeyaml.error.Mark;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.springframework.ide.vscode.yaml.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.commons.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.yaml.ast.YamlASTProvider;
|
||||
import org.springframework.ide.vscode.yaml.schema.YamlSchema;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package org.springframework.ide.vscode.yaml.reconcile;
|
||||
|
||||
import org.springframework.ide.vscode.commons.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemSeverity;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ProblemType;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,10 @@ import java.util.Set;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.springframework.ide.vscode.yaml.util.Description;
|
||||
import org.springframework.ide.vscode.util.EnumValueParser;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
import org.springframework.ide.vscode.util.ValueParser;
|
||||
import org.springframework.ide.vscode.yaml.util.DescriptionProviders;
|
||||
import org.springframework.ide.vscode.yaml.util.EnumValueParser;
|
||||
import org.springframework.ide.vscode.yaml.util.ValueParser;
|
||||
|
||||
/**
|
||||
* Static utility method for creating YType objects representing either
|
||||
@@ -193,7 +193,7 @@ public class YTypeFactory {
|
||||
propertyList.add(p);
|
||||
}
|
||||
|
||||
public void addProperty(String name, YType type, Provider<Description> description) {
|
||||
public void addProperty(String name, YType type, Provider<HtmlSnippet> description) {
|
||||
YTypedPropertyImpl prop;
|
||||
addProperty(prop = new YTypedPropertyImpl(name, type));
|
||||
prop.setDescriptionProvider(description);
|
||||
@@ -314,7 +314,7 @@ public class YTypeFactory {
|
||||
|
||||
final private String name;
|
||||
final private YType type;
|
||||
private Provider<Description> descriptionProvider = DescriptionProviders.NO_DESCRIPTION;
|
||||
private Provider<HtmlSnippet> descriptionProvider = DescriptionProviders.NO_DESCRIPTION;
|
||||
|
||||
private YTypedPropertyImpl(String name, YType type) {
|
||||
this.name = name;
|
||||
@@ -337,11 +337,11 @@ public class YTypeFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Description getDescription() {
|
||||
public HtmlSnippet getDescription() {
|
||||
return descriptionProvider.get();
|
||||
}
|
||||
|
||||
public void setDescriptionProvider(Provider<Description> descriptionProvider) {
|
||||
public void setDescriptionProvider(Provider<HtmlSnippet> descriptionProvider) {
|
||||
this.descriptionProvider = descriptionProvider;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ package org.springframework.ide.vscode.yaml.schema;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ide.vscode.yaml.util.ValueParser;
|
||||
import org.springframework.ide.vscode.util.ValueParser;
|
||||
|
||||
/**
|
||||
* An implementation of YTypeUtil provides implementations of various
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.schema;
|
||||
|
||||
import org.springframework.ide.vscode.yaml.util.Description;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
@@ -18,5 +18,5 @@ import org.springframework.ide.vscode.yaml.util.Description;
|
||||
public interface YTypedProperty {
|
||||
String getName();
|
||||
YType getType();
|
||||
Description getDescription();
|
||||
HtmlSnippet getDescription();
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.yaml.structure;
|
||||
|
||||
import org.springframework.ide.vscode.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.util.DocumentUtil;
|
||||
import org.springframework.ide.vscode.util.IDocument;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.DocumentUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SRootNode;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,9 +10,9 @@ import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.Assert;
|
||||
import org.springframework.ide.vscode.util.CollectionUtil;
|
||||
import org.springframework.ide.vscode.util.IRegion;
|
||||
import org.springframework.ide.vscode.util.StringUtil;
|
||||
import org.springframework.ide.vscode.yaml.path.KeyAliases;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlNavigable;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.springframework.ide.vscode.yaml.util;
|
||||
|
||||
public abstract class Description {
|
||||
|
||||
public abstract void renderAsText(StringBuilder buf);
|
||||
|
||||
public void renderAsHtml(StringBuilder buf) {
|
||||
throw new UnsupportedOperationException("Rendering as html not supported");
|
||||
}
|
||||
|
||||
public static Description text(String text) {
|
||||
return new Description() {
|
||||
@Override
|
||||
public void renderAsText(StringBuilder buf) {
|
||||
buf.append(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Description italic(Description d) {
|
||||
//Not really supported, we just ignore italic and display as is
|
||||
return d;
|
||||
}
|
||||
|
||||
public String toText() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
renderAsText(buf);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,8 +16,9 @@ import javax.inject.Provider;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.util.HtmlSnippet;
|
||||
|
||||
import static org.springframework.ide.vscode.yaml.util.Description.*;
|
||||
import static org.springframework.ide.vscode.util.HtmlSnippet.*;
|
||||
|
||||
/**
|
||||
* Static methods and convenience constants for creating some 'description providers'.
|
||||
@@ -28,33 +29,33 @@ public class DescriptionProviders {
|
||||
|
||||
final static Logger logger = LoggerFactory.getLogger(DescriptionProviders.class);
|
||||
|
||||
public static final Provider<Description> NO_DESCRIPTION = () -> italic(text("no description"));
|
||||
public static final Provider<HtmlSnippet> NO_DESCRIPTION = () -> italic(text("no description"));
|
||||
|
||||
public static Provider<Description> snippet(final Description snippet) {
|
||||
return new Provider<Description>() {
|
||||
public static Provider<HtmlSnippet> snippet(final HtmlSnippet snippet) {
|
||||
return new Provider<HtmlSnippet>() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return snippet.toString();
|
||||
}
|
||||
@Override
|
||||
public Description get() {
|
||||
public HtmlSnippet get() {
|
||||
return snippet;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Provider<Description> fromClasspath(final Class<?> klass, final String resourcePath) {
|
||||
return new Provider<Description>() {
|
||||
public static Provider<HtmlSnippet> fromClasspath(final Class<?> klass, final String resourcePath) {
|
||||
return new Provider<HtmlSnippet>() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DescriptionFromClassPth(class="+klass.getSimpleName()+", "+resourcePath+")";
|
||||
}
|
||||
@Override
|
||||
public Description get() {
|
||||
public HtmlSnippet get() {
|
||||
try {
|
||||
InputStream stream = klass.getResourceAsStream(resourcePath);
|
||||
if (stream!=null) {
|
||||
return Description.text(IOUtil.toString(stream));
|
||||
return HtmlSnippet.text(IOUtil.toString(stream));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error", e);;
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.util.TextDocument;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.TextDocument;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPath;
|
||||
import org.springframework.ide.vscode.yaml.path.YamlPathSegment;
|
||||
import org.springframework.ide.vscode.yaml.structure.YamlStructureParser.SChildBearingNode;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user