diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/completions/ValueCompletionProcessor.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/completions/ValueCompletionProcessor.java index 4c9d018b5..4a43b0f19 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/completions/ValueCompletionProcessor.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/java/completions/ValueCompletionProcessor.java @@ -19,7 +19,7 @@ import org.eclipse.jdt.core.dom.Annotation; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.StringLiteral; -import org.springframework.ide.vscode.boot.metadata.PropertyInfo; +import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap.Match; import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits; @@ -31,9 +31,9 @@ import org.springframework.ide.vscode.commons.util.text.IDocument; */ public class ValueCompletionProcessor { - private FuzzyMap index; + private FuzzyMap index; - public ValueCompletionProcessor(FuzzyMap index) { + public ValueCompletionProcessor(FuzzyMap index) { this.index = index; } @@ -43,9 +43,9 @@ public class ValueCompletionProcessor { try { // case: @Value(<*>) if (node == annotation && doc.get(offset - 1, 2).endsWith("()")) { - List> matches = findMatches(""); + List> matches = findMatches(""); - for (Match match : matches) { + for (Match match : matches) { DocumentEdits edits = new DocumentEdits(doc); edits.replace(offset, offset, "\"${" + match.data.getId() + "}\""); @@ -64,9 +64,9 @@ public class ValueCompletionProcessor { String proposalPrefix = "\""; String proposalPostfix = "\""; - List> matches = findMatches(prefix); + List> matches = findMatches(prefix); - for (Match match : matches) { + for (Match match : matches) { DocumentEdits edits = new DocumentEdits(doc); edits.replace(startOffset, endOffset, proposalPrefix + "${" + match.data.getId() + "}" + proposalPostfix); @@ -101,9 +101,9 @@ public class ValueCompletionProcessor { String fullNodeContent = doc.get(node.getStartPosition(), node.getLength()); String postCompletion = isClosingBracketMissing(fullNodeContent + preCompletion) ? "}" : ""; - List> matches = findMatches(prefix); + List> matches = findMatches(prefix); - for (Match match : matches) { + for (Match match : matches) { DocumentEdits edits = new DocumentEdits(doc); edits.replace(startOffset, endOffset, preCompletion + match.data.getId() + postCompletion); @@ -150,8 +150,8 @@ public class ValueCompletionProcessor { return result; } - private List> findMatches(String prefix) { - List> matches = index.find(camelCaseToHyphens(prefix)); + private List> findMatches(String prefix) { + List> matches = index.find(camelCaseToHyphens(prefix)); return matches; } diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/CachingValueProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/CachingValueProvider.java deleted file mode 100644 index 2b009422b..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/CachingValueProvider.java +++ /dev/null @@ -1,148 +0,0 @@ -/******************************************************************************* - * 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.metadata; - -import java.time.Duration; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy; -import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint; -import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.util.FuzzyMatcher; -import org.springframework.ide.vscode.commons.util.Log; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader.InvalidCacheLoadException; - -import reactor.core.publisher.Flux; -import reactor.util.function.Tuple2; -import reactor.util.function.Tuples; - -/** - * A abstract {@link ValueProviderStrategy} that is mean to help speedup successive invocations of - * content assist with a similar 'query' string. - *

- * This implementation is meant to be used for providers that use potentially lenghty/expensive searches - * to determine hints. Since content assist hints are requested by Eclipse CA framework directly on - * the UI thread, they can not simply perform a lengthy search and block UI thread until it finished. - *

- * This implementation therefore does the following: - *

    - *
  • Limit the duration of time spent on the UI thread. - *
  • Cache results of searches for a limited time. - *
  • Speedup queries for successive queries by using the already cached result of a similar (prefix) query. - *
  • When the time spent on UI thread waiting for a current search exceeds the allowed time limit, - * return immediately with whatever results have been found so far. - *
- * - * TODO: rather than an abstract class this should really be 'Wrapper' class that delegates to another - * {@link ValueProviderStrategy} and adds a cache in front of it. - * - * @author Kris De Volder - */ -public abstract class CachingValueProvider implements ValueProviderStrategy { - - private static final Duration DEFAULT_TIMEOUT = Duration.ofMillis(1000); - - /** - * Content assist is called inside UI thread and so doing something lenghty things - * like a JavaSearch will block the UI thread completely freezing the UI. So, we - * only return as many results as can be obtained within this hard TIMEOUT limit. - */ - public static Duration TIMEOUT = DEFAULT_TIMEOUT; - - /** - * The maximum number of results returned for a single request. Used to limit the - * values that are cached per entry. - */ - private int MAX_RESULTS = 500; - - private Cache, CacheEntry> cache = createCache(); - - private class CacheEntry { - boolean isComplete = false; - int count = 0; - Flux values; - - public CacheEntry(String query, Flux producer) { - values = producer - .take(MAX_RESULTS) - .cache(MAX_RESULTS); - values.subscribe(); // create infinite demand so that we actually force cache entries to be fetched upto the max. - } - - @Override - public String toString() { - return "CacheEntry [isComplete=" + isComplete + ", count=" + count + "]"; - } - - } - - @Override - public final Flux getValues(IJavaProject javaProject, String query) { - Tuple2 key = key(javaProject, query); - CacheEntry cached = null; - try { - cached = cache.get(key, () -> new CacheEntry(query, getValuesIncremental(javaProject, query))); - } catch (ExecutionException e) { - Log.log(e); - } - return cached.values; - } - - /** - * Tries to use an already cached, complete result for a query that is a prefix of the current query to speed things up. - *

- * Falls back on doing a full-blown search if there's no usable 'prefix-query' in the cache. - */ - private Flux getValuesIncremental(IJavaProject javaProject, String query) { -// debug("trying to solve "+query+" incrementally"); - String subquery = query; - while (subquery.length()>=1) { - subquery = subquery.substring(0, subquery.length()-1); - CacheEntry cached = null; - try { - cached = cache.get(key(javaProject, subquery), () -> null); - } catch (ExecutionException | InvalidCacheLoadException e) { -// Log.log(e); - } - if (cached!=null) { - System.out.println("cached "+subquery+": "+cached); - if (cached.isComplete) { - return cached.values -// .doOnNext((hint) -> debug("filter["+query+"]: "+hint.getValue())) - .filter((hint) -> 0!=FuzzyMatcher.matchScore(query, hint.getValue().toString())); - } else { -// debug("subquery "+subquery+" cached but is incomplete"); - } - } - } -// debug("full search for: "+query); - return getValuesAsync(javaProject, query); - } - - protected abstract Flux getValuesAsync(IJavaProject javaProject, String query); - - private Tuple2 key(IJavaProject javaProject, String query) { - return Tuples.of(javaProject==null?null:javaProject.getElementName(), query); - } - - protected Cache createCache() { - return CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).expireAfterAccess(1, TimeUnit.MINUTES).build(); - } - - public static void restoreDefaults() { - TIMEOUT = DEFAULT_TIMEOUT; - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ClassReferenceProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ClassReferenceProvider.java deleted file mode 100644 index 2618837bc..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ClassReferenceProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ - -package org.springframework.ide.vscode.boot.metadata; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy; -import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint; -import org.springframework.ide.vscode.commons.java.Flags; -import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.java.IType; -import org.springframework.ide.vscode.commons.util.Log; -import org.springframework.ide.vscode.commons.util.StringUtil; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; - -import reactor.core.publisher.Flux; - -/** - * Provides the algorithm for 'class-reference' valueProvider. - *

- * See: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-docs/src/main/asciidoc/appendix-configuration-metadata.adoc - * - * @author Kris De Volder - * @author Alex Boyko - */ -public class ClassReferenceProvider extends CachingValueProvider { - - /** - * Default value for the 'concrete' parameter. - */ - private static final boolean DEFAULT_CONCRETE = true; - - private static final ClassReferenceProvider UNTARGETTED_INSTANCE = new ClassReferenceProvider(null, DEFAULT_CONCRETE); - - public static final Function, ValueProviderStrategy> FACTORY = applyOn( - 1, TimeUnit.MINUTES, - (params) -> { - String target = getTarget(params); - Boolean concrete = getConcrete(params); - if (target!=null || concrete!=null) { - if (concrete==null) { - concrete = DEFAULT_CONCRETE; - } - return new ClassReferenceProvider(target, concrete); - } - return UNTARGETTED_INSTANCE; - } - ); - - private static Function applyOn(long duration, TimeUnit unit, Function func) { - Cache cache = CacheBuilder.newBuilder().expireAfterAccess(duration, unit).expireAfterWrite(duration, unit).build(); - return (k) -> { - try { - return cache.get(k, () -> func.apply(k)); - } catch (ExecutionException e) { - Log.log(e); - return null; - } - }; - } - - private static String getTarget(Map params) { - if (params!=null) { - Object obj = params.get("target"); - if (obj instanceof String) { - String target = (String) obj; - if (StringUtil.hasText(target)) { - return target; - } - } - } - return null; - } - - private static boolean isAbstract(IType type) { - try { - return type.isInterface() || Flags.isAbstract(type.getFlags()); - } catch (Exception e) { - Log.log(e); - return false; - } - } - - private static Boolean getConcrete(Map params) { - try { - if (params!=null) { - Object obj = params.get("concrete"); - if (obj instanceof String) { - String concrete = (String) obj; - return Boolean.valueOf(concrete); - } else if (obj instanceof Boolean) { - return (Boolean) obj; - } - } - } catch (Exception e) { - Log.log(e); - } - return null; - } - - /** - * Optional, fully qualified name of the 'target' type. Suggested hints should be a subtype of this type. - */ - private String target; - - /** - * Optional parameter, whether only concrete types should be suggested. Default value is true. - */ - private boolean concrete; - - private ClassReferenceProvider(String target, boolean concrete) { - this.target = target; - this.concrete = concrete; - } - - @Override - protected Flux getValuesAsync(IJavaProject javaProject, String query) { - IType targetType = target == null || target.isEmpty() ? javaProject.getClasspath().findType("java.lang.Object") : javaProject.getClasspath().findType(target); - if (targetType == null) { - return Flux.empty(); - } - Set allSubclasses = javaProject.getClasspath() - .allSubtypesOf(targetType) - .filter(t -> Flags.isPublic(t.getFlags()) && !concrete || !isAbstract(t)) - .collect(Collectors.toSet()) - .block(); - if (allSubclasses.isEmpty()) { - return Flux.empty(); - } else { - return javaProject.getClasspath() - .fuzzySearchTypes(query, type -> allSubclasses.contains(type)) - .collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())) - .flatMap(l -> Flux.fromIterable(l)) - .map(t -> StsValueHint.create(t.getT1())); - } - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java index 0e379d645..96b11c23b 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/DefaultSpringPropertyIndexProvider.java @@ -11,6 +11,7 @@ package org.springframework.ide.vscode.boot.metadata; +import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.ProgressService; @@ -19,10 +20,10 @@ import org.springframework.ide.vscode.commons.util.text.IDocument; public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexProvider { - private static final FuzzyMap EMPTY_INDEX = new SpringPropertyIndex(null, null); + private static final FuzzyMap EMPTY_INDEX = new SpringPropertyIndex(null); private JavaProjectFinder javaProjectFinder; - private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(ValueProviderRegistry.getDefault()); + private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(); private ProgressService progressService = (id, msg) -> { /*ignore*/ }; @@ -31,7 +32,7 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr } @Override - public FuzzyMap getIndex(IDocument doc) { + public FuzzyMap getIndex(IDocument doc) { IJavaProject jp = javaProjectFinder.find(doc); if (jp!=null) { return indexManager.get(jp, progressService); diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/IndexNavigator.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/IndexNavigator.java deleted file mode 100644 index cd19604c6..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/IndexNavigator.java +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * 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.metadata; - -import static org.springframework.ide.vscode.commons.util.StringUtil.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; -import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap.Match; -import org.springframework.ide.vscode.commons.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 index; - - private IndexNavigator(FuzzyMap index) { - this.index = index; - } - - private IndexNavigator(FuzzyMap index, String prefix) { - this.index = index; - this.prefix = prefix; - } - - public static IndexNavigator with(FuzzyMap 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> findMatching(String query) { - if (!StringUtil.hasText(prefix)) { - return index.find(query); - } else { - String dottedPrefix = prefix +"."; - List> candidates = index.find(dottedPrefix + query); - if (!candidates.isEmpty()) { - //TODO: we can do better than this using treemap to narrow based on - // prefix - List> matches = new ArrayList>(candidates.size()); - for (Match 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; - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/LoggerNameProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/LoggerNameProvider.java deleted file mode 100644 index 2f9886766..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/LoggerNameProvider.java +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ - -package org.springframework.ide.vscode.boot.metadata; - -import java.util.Map; -import java.util.function.Function; - -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy; -import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint; -import org.springframework.ide.vscode.commons.java.IJavaProject; - -import reactor.core.publisher.Flux; -import reactor.util.function.Tuples; - -/** - * Provides the algorithm for 'logger-name' valueProvider. - *

- * See: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-docs/src/main/asciidoc/appendix-configuration-metadata.adoc - * - * @author Kris De Volder - * @author Alex Boyko - */ -public class LoggerNameProvider extends CachingValueProvider { - - private static final ValueProviderStrategy INSTANCE = new LoggerNameProvider(); - public static final Function, ValueProviderStrategy> FACTORY = (params) -> INSTANCE; - - @Override - protected Flux getValuesAsync(IJavaProject javaProject, String query) { - return Flux.concat( - javaProject.getClasspath() - .fuzzySearchPackages(query) - .map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())), - javaProject.getClasspath() - .fuzzySearchTypes(query, null) - .map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())) - ) - .collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())) - .flatMap(l -> Flux.fromIterable(l)) - .map(t -> t.getT1()); - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/MetadataManipulator.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/MetadataManipulator.java deleted file mode 100644 index ed10f06c7..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/MetadataManipulator.java +++ /dev/null @@ -1,235 +0,0 @@ -/******************************************************************************* - * 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.metadata; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.LinkedHashMap; - -import org.json.JSONArray; -import org.json.JSONObject; - -/** - * Helper class to manipulate data in a file presumed to contain - * spring-boot configuration data. - * - * @author Kris De Volder - * @author Alex Boyko - */ -public class MetadataManipulator { - - private abstract class Content { - public abstract String toString(); - public abstract void addProperty(JSONObject jsonObject) throws Exception; - } - - /** - * Content was parse as JSONObject. - */ - private class ParsedContent extends Content { - - private JSONObject object; - - public ParsedContent(JSONObject o) { - this.object = o; - } - - public String toString() { - try { - return object.toString(indentFactor); - } - catch (Exception e) { - return null; - } - } - - @Override - public void addProperty(JSONObject propertyData) throws Exception { - JSONArray properties = object.getJSONArray("properties"); - properties.put(properties.length(), propertyData); - } - } - - /** - * Content that is 'unparsed' and just a bunch of text. - * Used only as a fallback when data in file can't - * be parsed. - *

- * This content is manipulated by string manipulation. - * It is less reliable, but can be done even if the - * file data is not parseable. - */ - private class RawContent extends Content { - - private StringBuilder doc; - - public RawContent(String content) { - this.doc = new StringBuilder(content); - } - - @Override - public String toString() { - return doc.toString(); - } - - @Override - public void addProperty(JSONObject propertyData) throws Exception { - int insertAt = findLast(']'); - if (insertAt<0) { - //although we're not looking for much, we didn't find it! - //Funky file contents. Let's just insert something at end of file in a 'best effort' spirit. - insertAt = doc.length(); - } - insert(insertAt, "\n"); - - insert(insertAt, propertyData.toString(indentFactor)); - - int insertComma = findInsertCommaPos(insertAt); - if (insertComma>=0) { - insert(insertComma, ","); - } - } - - /** - * Maybe we need to add a comma in front of the new entry. This - * method finds if/where to stick this comma. - * @throws Exception - */ - private int findInsertCommaPos(int pos) throws Exception { - pos--; - while (pos>=0 && Character.isWhitespace(doc.charAt(pos))) { - pos--; - } - if (pos>=0) { - char c = doc.charAt(pos); - if (c == '}') { - //Add a comma after a '}' - return pos+1; - } - } - return -1; - } - - private int insert(int insertAt, String str) throws Exception { - if (insertAt < doc.length()) { - doc.replace(insertAt, insertAt, str); - } else { - doc.append(str); - } - return insertAt + str.length(); - } - - private int findLast(char toFind) throws Exception { - int pos = doc.length()-1; - while (pos>=0 && doc.charAt(pos)!=toFind) { - pos--; - } - //We got here either because - // - we found char at pos or.. - // - we reached position *before* start of file (i.e. -1) - return pos; - } - - } - - public interface ContentStore { - String getContents() throws Exception; - void setContents(String content) throws Exception; - } - - private static final String INITIAL_CONTENT = - "{\"properties\": [\n" + - "]}"; - - private static final String ENCODING = "UTF8"; - private ContentStore contentStore; - private Content fContent; - private int indentFactor = 2; - - public MetadataManipulator(ContentStore contentStore) { - this.contentStore = contentStore; - } - - public MetadataManipulator(final File file) { - this(new ContentStore() { - - @Override - public String getContents() throws Exception { - return new String(Files.readAllBytes(Paths.get(file.toURI())), ENCODING); - } - - @Override - public void setContents(String content) throws Exception { - Files.write(Paths.get(file.toURI()), content.getBytes(ENCODING)); - } - - }); - } - - private Content getContent() throws Exception { - if (fContent==null) { - fContent = readContent(); - } - return fContent; - } - - private Content readContent() throws Exception { - String content = contentStore.getContents(); - if (content.trim().isEmpty()) { - JSONObject o = initialContent(); - return new ParsedContent(o); - } else { - try { - return new ParsedContent(new JSONObject(content)); - } catch (Exception e) { - //couldn't parse? - return new RawContent(content); - } - } - } - - public void addDefaultInfo(String propertyName) throws Exception { - getContent().addProperty(createDefaultData(propertyName)); - } - - private JSONObject createDefaultData(String propertyName) throws Exception { - JSONObject obj = new JSONObject(new LinkedHashMap()); - obj.put("name", propertyName); - obj.put("type", String.class.getName()); - obj.put("description", "A description for '"+propertyName+"'"); - return obj; - } - - /** - * Generate the initial content (must be generated rather than being a constant to respect newline conventions - * on user's system. - */ - private JSONObject initialContent() throws Exception { - return new JSONObject(INITIAL_CONTENT); - } - - /** - * After manipulating the data, use this to persist changes back to the file. - */ - public void save() throws Exception { - contentStore.setContents(getContent().toString()); - } - - /** - * Determines whether the 'reliable' manipulations can be used (which is the case - * only if the data in the file is valid json). - */ - public boolean isReliable() throws Exception { - return getContent() instanceof ParsedContent; - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java index e3d6e66f8..79779f133 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertiesLoader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. + * Copyright (c) 2016, 2017 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertyInfo.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertyInfo.java deleted file mode 100644 index 4b3342f03..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/PropertyInfo.java +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * 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.boot.metadata; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; -import org.springframework.boot.configurationmetadata.ConfigurationMetadataSource; -import org.springframework.boot.configurationmetadata.Deprecation; -import org.springframework.boot.configurationmetadata.ValueHint; -import org.springframework.boot.configurationmetadata.ValueProvider; -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; - -/** - * Information about a spring property, basically, this is the same as - * - * {@link ConfigurationMetadataProperty} but augmented with information - * about {@link ConfigurationMetadataSource}s that declare the property. - * - * @author Kris De Volder - */ -public class PropertyInfo { - - /** - * Identifies a 'Source'. This is essentially the sames as {@link ConfigurationMetadataSource}. - * We could use {@link ConfigurationMetadataSource} directly, but this only contains - * the info that we actually use so takes less memory. - */ - public static class PropertySource { - private final String sourceType; - private final String sourceMethod; - public PropertySource(ConfigurationMetadataSource source) { - String st = source.getSourceType(); - this.sourceType = st!=null?st:source.getType(); - this.sourceMethod = source.getSourceMethod(); - } - @Override - public String toString() { - return sourceType+"::"+sourceMethod; - } - public String getSourceType() { - return sourceType; - } - public String getSourceMethod() { - return sourceMethod; - } - } - - final private String id; - private String type; - final private String name; - final private Object defaultValue; - final private String description; - private List sources; - private Deprecation deprecation; - private ImmutableList valueHints; - private ImmutableList keyHints; - private ValueProviderStrategy valueProvider; - private ValueProviderStrategy keyProvider; - - public PropertyInfo(String id, String type, String name, - Object defaultValue, String description, - Deprecation deprecation, - List valueHints, - List keyHints, - ValueProviderStrategy valueProvider, - ValueProviderStrategy keyProvider, - List sources) { - super(); - this.id = id; - this.type = type; - this.name = name; - this.defaultValue = defaultValue; - this.description = description; - this.deprecation = deprecation; - this.valueHints = valueHints==null?null:ImmutableList.copyOf(valueHints); - this.keyHints = keyHints==null?null:ImmutableList.copyOf(keyHints); - this.valueProvider = valueProvider; - this.keyProvider = keyProvider; - this.sources = sources; - } - public PropertyInfo(ValueProviderRegistry valueProviders, ConfigurationMetadataProperty prop) { - this( - prop.getId(), - prop.getType(), - prop.getName(), - prop.getDefaultValue(), - prop.getDescription(), - prop.getDeprecation(), - prop.getHints().getValueHints(), - prop.getHints().getKeyHints(), - valueProviders.resolve(prop.getHints().getValueProviders()), - valueProviders.resolve(prop.getHints().getKeyProviders()), - null - ); - for (ValueProvider h : prop.getHints().getValueProviders()) { - if (h.getName().equals("handle-as")) { - handleAs(h.getParameters().get("target")); - } - } - } - private void handleAs(Object targetObject) { -// debug("handle-as "+this.getId()+" -> "+targetObject); - if (targetObject instanceof String) { - this.type = (String)targetObject; - } - } - public String getId() { - return id; - } - public String getType() { - return type; - } - public String getName() { - return name; - } - public Object getDefaultValue() { - return defaultValue; - } - public String getDescription() { - return description; - } - - public List getSources() { - if (sources!=null) { - return sources; - } - return Collections.emptyList(); - } - - @Override - public String toString() { - return "PropertyInfo("+getId()+")"; - } - public void addSource(ConfigurationMetadataSource source) { - if (sources==null) { - sources = new ArrayList(); - } - sources.add(new PropertySource(source)); - } - - public PropertyInfo withId(String alias) { - if (alias.equals(id)) { - return this; - } - return new PropertyInfo(alias, type, name, defaultValue, description, deprecation, valueHints, keyHints, valueProvider, keyProvider, sources); - } - - public void setDeprecation(Deprecation d) { - this.deprecation = d; - } - - public boolean isDeprecated() { - return deprecation!=null; - } - - public String getDeprecationReason() { - return deprecation == null ? null : deprecation.getReason(); - } - - public String getDeprecationReplacement() { - return deprecation == null ? null : deprecation.getReplacement(); - } - - public void addValueHints(List hints) { - Builder builder = ImmutableList.builder(); - builder.addAll(valueHints); - builder.addAll(hints); - valueHints = builder.build(); - } - public void addKeyHints(List hints) { - Builder builder = ImmutableList.builder(); - builder.addAll(keyHints); - builder.addAll(hints); - keyHints = builder.build(); - } -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ResourceHintProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ResourceHintProvider.java deleted file mode 100644 index beb3891ee..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ResourceHintProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ - -package org.springframework.ide.vscode.boot.metadata; - -import java.util.Arrays; -import java.util.stream.Collectors; - -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry.ValueProviderStrategy; -import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint; -import org.springframework.ide.vscode.commons.java.IJavaProject; - -import com.google.common.collect.ImmutableList; - -import reactor.core.publisher.Flux; - -/** - * @author Kris De Volder - */ -public class ResourceHintProvider implements ValueProviderStrategy { - - private static String[] CLASSPATH_PREFIXES = { - "classpath:", - "classpath*:" - }; - - private static final String[] URL_PREFIXES = new String[] { - "classpath:", - "classpath*:", - "file:", - "http://", - "https://" - }; - - @Override - public Flux getValues(IJavaProject javaProject, String query) { - for (String prefix : CLASSPATH_PREFIXES) { - if (query.startsWith(prefix)) { - return classpathHints - .getValues(javaProject, query.substring(prefix.length())) - .map((hint) -> hint.prefixWith(prefix)); - } - } - return Flux.fromIterable(urlPrefixHints); - } - - final private ImmutableList urlPrefixHints = ImmutableList.copyOf( - Arrays.stream(URL_PREFIXES) - .map(StsValueHint::create) - .collect(Collectors.toList()) - ); - - private ClasspathHints classpathHints = new ClasspathHints(); - - private static class ClasspathHints extends CachingValueProvider { - @Override - protected Flux getValuesAsync(IJavaProject javaProject, String query) { - return Flux.fromStream(javaProject.getClasspath().getClasspathResources().distinct().map(StsValueHint::create)); - } - } - - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertiesIndexManager.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertiesIndexManager.java index d88075998..289050e7b 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertiesIndexManager.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertiesIndexManager.java @@ -13,9 +13,8 @@ package org.springframework.ide.vscode.boot.metadata; import java.util.HashMap; import java.util.Map; +import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; -import org.springframework.ide.vscode.boot.metadata.util.Listener; -import org.springframework.ide.vscode.boot.metadata.util.ListenerManager; import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.languageserver.ProgressService; @@ -27,20 +26,19 @@ import org.springframework.ide.vscode.commons.languageserver.ProgressService; * * @author Kris De Volder */ -public class SpringPropertiesIndexManager extends ListenerManager> { +public class SpringPropertiesIndexManager { private Map indexes = null; - private final ValueProviderRegistry valueProviders; private static int progressIdCt = 0; - public SpringPropertiesIndexManager(ValueProviderRegistry valueProviders) { - this.valueProviders = valueProviders; + public SpringPropertiesIndexManager() { } - public synchronized FuzzyMap get(IJavaProject project, ProgressService progressService) { + public synchronized FuzzyMap get(IJavaProject project, ProgressService progressService) { if (indexes==null) { indexes = new HashMap<>(); } + SpringPropertyIndex index = indexes.get(project); if (index==null) { String progressId = getProgressId(); @@ -48,7 +46,7 @@ public class SpringPropertiesIndexManager extends ListenerManager l : getListeners()) { - l.changed(this); - } - } - } private static synchronized String getProgressId() { return DefaultSpringPropertyIndexProvider.class.getName()+ (progressIdCt++); diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndex.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndex.java index b21ed7bef..5784dc64e 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndex.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndex.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Pivotal, Inc. + * Copyright (c) 2015, 2017 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,71 +11,41 @@ package org.springframework.ide.vscode.boot.metadata; import java.util.Collection; -import java.util.List; -import org.springframework.boot.configurationmetadata.ConfigurationMetadataGroup; import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.boot.configurationmetadata.ConfigurationMetadataRepository; -import org.springframework.boot.configurationmetadata.ConfigurationMetadataSource; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; import org.springframework.ide.vscode.commons.java.IClasspath; -import org.springframework.ide.vscode.commons.util.StringUtil; -public class SpringPropertyIndex extends FuzzyMap { +public class SpringPropertyIndex extends FuzzyMap { - private ValueProviderRegistry valueProviders; - - public SpringPropertyIndex(ValueProviderRegistry valueProviders, IClasspath projectPath) { - this.valueProviders = valueProviders; + public SpringPropertyIndex(IClasspath projectPath) { if (projectPath!=null) { -// try { - PropertiesLoader loader = new PropertiesLoader(); - ConfigurationMetadataRepository metadata = loader.load(projectPath); - //^^^ Should be done in bg? It seems fast enough for now. - - Collection allEntries = metadata.getAllProperties().values(); - for (ConfigurationMetadataProperty item : allEntries) { - add(new PropertyInfo(valueProviders, item)); - } - - for (ConfigurationMetadataGroup group : metadata.getAllGroups().values()) { - for (ConfigurationMetadataSource source : group.getSources().values()) { - for (ConfigurationMetadataProperty prop : source.getProperties().values()) { - PropertyInfo info = get(prop.getId()); - info.addSource(source); - } - } - } - - // System.out.println(">>> spring properties metadata loaded "+this.size()+" items==="); - // dumpAsTestData(); - // System.out.println(">>> spring properties metadata loaded "+this.size()+" items==="); -// } catch (Exception e) { -// LOG.log -// } + PropertiesLoader loader = new PropertiesLoader(); + ConfigurationMetadataRepository metadata = loader.load(projectPath); + Collection allEntries = metadata.getAllProperties().values(); + for (ConfigurationMetadataProperty item : allEntries) { + add(item); + } } } - public void add(ConfigurationMetadataProperty propertyInfo) { - add(new PropertyInfo(valueProviders, propertyInfo)); - } - /** * Dumps out 'test data' based on the current contents of the index. This is not meant to be * used in 'production' code. The idea is to call this method during development to dump a * 'snapshot' of the index onto System.out. The data is printed in a forma so that it can be easily * pasted/used into JUNit testing code. */ - public void dumpAsTestData() { - List> allData = this.find(""); - for (Match match : allData) { - PropertyInfo d = match.data; - System.out.println("data(" - +dumpString(d.getId())+", " - +dumpString(d.getType())+", " - +dumpString(d.getDefaultValue())+", " - +dumpString(d.getDescription()) +");" - ); +// public void dumpAsTestData() { +// List> allData = this.find(""); +// for (Match match : allData) { +// PropertyInfo d = match.data; +// System.out.println("data(" +// +dumpString(d.getId())+", " +// +dumpString(d.getType())+", " +// +dumpString(d.getDefaultValue())+", " +// +dumpString(d.getDescription()) +");" +// ); // for (PropertySource source : d.getSources()) { // String st = source.getSourceType(); // String sm = source.getSourceMethod(); @@ -83,15 +53,15 @@ public class SpringPropertyIndex extends FuzzyMap { // System.out.println(d.getId() +" from: "+st+"::"+sm); // } // } - } - } +// } +// } - private String dumpString(Object v) { - if (v==null) { - return "null"; - } - return dumpString(""+v); - } +// private String dumpString(Object v) { +// if (v==null) { +// return "null"; +// } +// return dumpString(""+v); +// } private String dumpString(String s) { if (s==null) { @@ -123,7 +93,7 @@ public class SpringPropertyIndex extends FuzzyMap { } @Override - protected String getKey(PropertyInfo entry) { + protected String getKey(ConfigurationMetadataProperty entry) { return entry.getId(); } @@ -132,25 +102,25 @@ public class SpringPropertyIndex extends FuzzyMap { * 'string prefix' but a prefix in the sense of treating '.' as a kind of separators. So * 'prefix' is not allowed to end in the middle of a 'segment'. */ - public static PropertyInfo findLongestValidProperty(FuzzyMap index, String name) { - int bracketPos = name.indexOf('['); - int endPos = bracketPos>=0?bracketPos:name.length(); - PropertyInfo prop = null; - String prefix = null; - while (endPos>0 && prop==null) { - prefix = name.substring(0, endPos); - String canonicalPrefix = StringUtil.camelCaseToHyphens(prefix); - prop = index.get(canonicalPrefix); - if (prop==null) { - endPos = name.lastIndexOf('.', endPos-1); - } - } - if (prop!=null) { - //We should meet caller's expectation that matched properties returned by this method - // match the names exactly even if we found them using relaxed name matching. - return prop.withId(prefix); - } - return null; - } +// public static PropertyInfo findLongestValidProperty(FuzzyMap index, String name) { +// int bracketPos = name.indexOf('['); +// int endPos = bracketPos>=0?bracketPos:name.length(); +// PropertyInfo prop = null; +// String prefix = null; +// while (endPos>0 && prop==null) { +// prefix = name.substring(0, endPos); +// String canonicalPrefix = StringUtil.camelCaseToHyphens(prefix); +// prop = index.get(canonicalPrefix); +// if (prop==null) { +// endPos = name.lastIndexOf('.', endPos-1); +// } +// } +// if (prop!=null) { +// //We should meet caller's expectation that matched properties returned by this method +// // match the names exactly even if we found them using relaxed name matching. +// return prop.withId(prefix); +// } +// return null; +// } } diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndexProvider.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndexProvider.java index 41f750fb0..570996f5a 100644 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndexProvider.java +++ b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/SpringPropertyIndexProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Pivotal, Inc. + * Copyright (c) 2015, 2017 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,11 +10,12 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.metadata; +import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; import org.springframework.ide.vscode.commons.util.text.IDocument; @FunctionalInterface public interface SpringPropertyIndexProvider { - FuzzyMap getIndex(IDocument doc); + FuzzyMap getIndex(IDocument doc); } diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ValueProviderRegistry.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ValueProviderRegistry.java deleted file mode 100644 index c7032b3de..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/ValueProviderRegistry.java +++ /dev/null @@ -1,98 +0,0 @@ -/******************************************************************************* - * 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.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.metadata.hints.StsValueHint; -import org.springframework.ide.vscode.commons.java.IJavaProject; -import org.springframework.ide.vscode.commons.util.CollectionUtil; - -import reactor.core.publisher.Flux; - -/** - * An instance of this class serves as a 'registry' that associates known - * {@link ValueProvider} ids to strategy objects used in the computation of completions - * for properties to which the provider is attached. - * - * @author Kris De Volder - */ -public class ValueProviderRegistry { - - private static ValueProviderRegistry DEFAULT; - - /** - * Creates a default {@link ValueProviderRegistry} which is initialized with all the known - * providers. (This is the one production code should use, test code might make use - * something else for mocking purposes). - */ - public synchronized static ValueProviderRegistry getDefault() { - if (DEFAULT==null) { - DEFAULT = new ValueProviderRegistry(); - DEFAULT.initializeDefaults(DEFAULT); - } - return DEFAULT; - } - - protected void initializeDefaults(ValueProviderRegistry r) { - def("logger-name", LoggerNameProvider.FACTORY); - def("class-reference", ClassReferenceProvider.FACTORY); - } - - private Map, ValueProviderStrategy>> registry = new HashMap<>(); - - public interface ValueProviderStrategy { - Flux getValues(IJavaProject javaProject, String query); - - default Collection getValuesNow(IJavaProject javaProject, String query) { - return this.getValues(javaProject, query) - .take(CachingValueProvider.TIMEOUT) - .collectList() - .block(); - } - } - - /** - * Defines a value provider by binding its id to a strategy. - */ - public void def(String id, Function, ValueProviderStrategy> algo) { - registry.put(id, algo); - } - - /** - * Resolve a list of {@link ValueProvider}s to a {@link ValueProviderStrategy}. - *

- * Essentially this finds the first provider from the list which has a known name - * and uses that to iinstantiate a ValueProviderStrategy. Spring boot assumes that - * a list is provided to allow new providers to be defined that override older ones - * and these are added at the top of the list. Thus an older IDE can continue to - * function using the older provider further down the list whereas newer IDEs will - * use a 'better' one from higher up the list. - */ - public ValueProviderStrategy resolve(List providerDescriptors) { - if (CollectionUtil.hasElements(providerDescriptors)) { - for (ValueProvider descriptor : providerDescriptors) { - Function, ValueProviderStrategy> factory = registry.get(descriptor.getName()); - if (factory!=null) { - Map params = descriptor.getParameters(); - return factory.apply(params); - } - } - } - return null; - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/StsValueHint.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/StsValueHint.java deleted file mode 100644 index 33a565d4d..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/StsValueHint.java +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ - -package org.springframework.ide.vscode.boot.metadata.hints; - -import org.springframework.boot.configurationmetadata.Deprecation; -import org.springframework.boot.configurationmetadata.ValueHint; -import org.springframework.ide.vscode.boot.metadata.util.DeprecationUtil; -import org.springframework.ide.vscode.commons.java.IJavaElement; -import org.springframework.ide.vscode.commons.java.IType; -import org.springframework.ide.vscode.commons.javadoc.IJavadoc; -import org.springframework.ide.vscode.commons.util.Assert; -import org.springframework.ide.vscode.commons.util.Renderable; -import org.springframework.ide.vscode.commons.util.Renderables; -import org.springframework.ide.vscode.commons.util.StringUtil; - -/** - * Sts version of {@link ValueHint} contains similar data, but accomoates - * a html snippet to be computed lazyly for the description. - *

- * 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 final String value; - private final Renderable description; - private final Deprecation deprecation; - - /** - * Create a hint with a textual description. - *

- * This constructor is private. Use one of the provided - * static 'create' methods instead. - */ - private StsValueHint(String value, Renderable 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, Renderables.NO_DESCRIPTION, null); - } - - public static StsValueHint create(ValueHint hint) { - return new StsValueHint(""+hint.getValue(), textSnippet(hint.getDescription()), 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 Renderable textSnippet(String description) { - if (StringUtil.hasText(description)) { - return Renderables.text(description); - } - return Renderables.NO_DESCRIPTION; - } - - public String getValue() { - return value; - } - - public Renderable getDescription() { - return description; - } - - private static Renderable javaDocSnippet(IJavaElement je) { - return Renderables.lazy(() -> { - IJavadoc jdoc = je.getJavaDoc(); - if (jdoc != null) { - return jdoc.getRenderable(); - } else { - return Renderables.NO_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(); - } - }; - } - - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/ValueHintHoverInfo.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/ValueHintHoverInfo.java deleted file mode 100644 index 2ce773fe9..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/hints/ValueHintHoverInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016-2017 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ - -package org.springframework.ide.vscode.boot.metadata.hints; - -import java.util.List; - -import org.springframework.ide.vscode.commons.util.Renderable; -import org.springframework.ide.vscode.commons.util.Renderables; - -import static org.springframework.ide.vscode.commons.util.Renderables.*; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableList.Builder; - -public class ValueHintHoverInfo { - - public static Renderable create(StsValueHint hint) { - Builder builder = ImmutableList.builder(); - builder.add(bold(""+hint.getValue())); - builder.add(paragraph(hint.getDescription())); - return concat(builder.build()); - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/DeprecationUtil.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/DeprecationUtil.java deleted file mode 100644 index 9d9cd78b3..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/DeprecationUtil.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * 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.metadata.util; - -import java.util.Optional; - -import org.springframework.boot.configurationmetadata.Deprecation; -import org.springframework.ide.vscode.commons.java.IAnnotatable; -import org.springframework.ide.vscode.commons.java.IJavaElement; - -import com.google.common.collect.ImmutableSet; - -public class DeprecationUtil { - - private static final ImmutableSet 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) { - Optional deprecation = Optional.empty(); - if (je instanceof IAnnotatable) { - deprecation = extract((IAnnotatable)je); - } - return deprecation.isPresent() ? deprecation.get() : null; - } - - /** - * Extract {@link Deprecation} info from annotations on a {@link IJavaElement} - */ - private static Optional extract(IAnnotatable m) { - return m.getAnnotations().filter(a -> DEPRECATED_ANOT_NAMES.contains(a.getElementName())).map(a -> { - Deprecation d = new Deprecation(); - a.getMemberValuePairs().forEach(pair -> { - 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; - }).findFirst(); - } - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/Listener.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/Listener.java deleted file mode 100644 index 10aa67fdc..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/Listener.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ -package org.springframework.ide.vscode.boot.metadata.util; - -/** - * @author Kris De Volder - */ -public interface Listener { - - void changed(T info); - -} diff --git a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/ListenerManager.java b/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/ListenerManager.java deleted file mode 100644 index f3921598a..000000000 --- a/vscode-extensions/vscode-boot-java/src/main/java/org/springframework/ide/vscode/boot/metadata/util/ListenerManager.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Pivotal, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Pivotal, Inc. - initial API and implementation - *******************************************************************************/ -package org.springframework.ide.vscode.boot.metadata.util; - -import java.util.Arrays; - -import org.springframework.ide.vscode.commons.util.ListenerList; - -public class ListenerManager { - - private ListenerList listeners = new ListenerList<>(ListenerList.IDENTITY); - - public void addListener(T l) { - listeners.add(l); - } - - public void removeListener(T l) { - listeners.remove(l); - } - - @SuppressWarnings("unchecked") - public Iterable getListeners() { - return (Iterable) Arrays.asList(listeners.getListeners()); - } - - - -} diff --git a/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/project/harness/PropertyIndexHarness.java b/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/project/harness/PropertyIndexHarness.java index ab1063e03..cb008c92f 100644 --- a/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/project/harness/PropertyIndexHarness.java +++ b/vscode-extensions/vscode-boot-java/src/test/java/org/springframework/ide/vscode/project/harness/PropertyIndexHarness.java @@ -18,10 +18,8 @@ import org.springframework.boot.configurationmetadata.ConfigurationMetadataPrope import org.springframework.boot.configurationmetadata.Deprecation; import org.springframework.boot.configurationmetadata.ValueHint; import org.springframework.boot.configurationmetadata.ValueProvider; -import org.springframework.ide.vscode.boot.metadata.PropertyInfo; import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndex; import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider; -import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry; import org.springframework.ide.vscode.boot.metadata.util.FuzzyMap; import org.springframework.ide.vscode.commons.java.IClasspath; import org.springframework.ide.vscode.commons.java.IJavaProject; @@ -33,17 +31,16 @@ import org.springframework.ide.vscode.commons.util.text.IDocument; public class PropertyIndexHarness { private Map datas = new LinkedHashMap<>(); - private ValueProviderRegistry valueProviders = ValueProviderRegistry.getDefault(); private SpringPropertyIndex index = null; private IJavaProject testProject = null; protected final SpringPropertyIndexProvider indexProvider = new SpringPropertyIndexProvider() { @Override - public FuzzyMap getIndex(IDocument doc) { + public FuzzyMap getIndex(IDocument doc) { synchronized (PropertyIndexHarness.this) { if (index==null) { IClasspath classpath = testProject == null ? null : testProject.getClasspath(); - index = new SpringPropertyIndex(valueProviders, classpath); + index = new SpringPropertyIndex(classpath); for (ConfigurationMetadataProperty propertyInfo : datas.values()) { index.add(propertyInfo); }