matchesRootTillMe, final int numOfAncestors) {
+
+ final Suggestion.SuggestionBuilder builder = Suggestion.builder()
+ .suggestionToDisplay(GenericUtil.dotDelimitedOriginalNames(matchesRootTillMe, numOfAncestors))
+ .description(description)
+ .shortType(shortenedType(className))
+ .defaultValue(getDefaultValueAsStr())
+ .numOfAncestors(numOfAncestors)
+ .matchesTopFirst(matchesRootTillMe)
+ .icon(getSuggestionNodeType(module).getIcon());
+
+ if (deprecation != null) {
+ builder.deprecationLevel(deprecation.getLevel() != null ? deprecation.getLevel() : SpringConfigurationMetadataDeprecationLevel.warning);
+ }
- if (deprecation.getReplacement() != null) {
- builder.append("Replaced by property ").append(deprecation.getReplacement())
- .append("
");
- }
+ return builder.fileType(fileType).build();
}
- return builder.toString();
- }
+ @NotNull
+ public String getDocumentationForKey(String nodeNavigationPathDotDelimited) {
+ // Format for the documentation is as follows
+ /*
+ * a.b.c ({@link com.acme.Generic}<{@link com.acme.Class1}, {@link com.acme.Class2}>)
+ * Default Value default value
+ * Long description
+ * or of this type
+ * Type {@link com.acme.Array}[]
+ * Declared at{@link com.acme.GenericRemovedClass#method}>
<-- only for groups with method info
+ * WARNING:
+ * @deprecated Due to something something. Replaced by c.d.e
+ */
+ StringBuilder builder =
+ new StringBuilder().append("").append(nodeNavigationPathDotDelimited).append("");
+
+ if (className != null) {
+ builder.append(" (");
+ updateClassNameAsJavadocHtml(builder, className);
+ builder.append(")");
+ }
+
+ if (description != null) {
+ builder.append("").append(description).append("
");
+ }
- public boolean isLeaf(Module module) {
- return isLeafWithKnownValues() || getSuggestionNodeType(module).representsLeaf()
- || doWithDelegateOrReturnDefault(module, delegate -> delegate.isLeaf(module), true);
- }
+ if (defaultValue != null) {
+ builder.append("Default value: ").append(getDefaultValueAsStr()).append("
");
+ }
- @NotNull
- public SuggestionNodeType getSuggestionNodeType(Module module) {
- if (nodeType == null) {
- if (className != null) {
- refreshDelegate(module);
+ if (sourceType != null) {
+ String sourceTypeInJavadocFormat = removeGenerics(sourceType);
- if (delegate != null) {
- nodeType = delegate.getSuggestionNodeType(module);
+ // lets show declaration point only if does not match the type
+ if (!sourceTypeInJavadocFormat.equals(removeGenerics(className))) {
+ StringBuilder buffer = new StringBuilder();
+ createHyperlink(buffer, methodForDocumentationNavigation(sourceTypeInJavadocFormat),
+ sourceTypeInJavadocFormat, false);
+ sourceTypeInJavadocFormat = buffer.toString();
+
+ builder.append("Declared at ").append(sourceTypeInJavadocFormat).append("
");
+ }
}
- if (nodeType == null) {
- nodeType = UNKNOWN_CLASS;
+ if (deprecation != null) {
+ builder.append("").append(isDeprecatedError() ?
+ "ERROR: DO NOT USE THIS PROPERTY AS IT IS COMPLETELY UNSUPPORTED" :
+ "WARNING: PROPERTY IS DEPRECATED").append("
");
+
+ if (deprecation.getReason() != null) {
+ builder.append("@deprecated Reason: ").append(deprecation.getReason());
+ }
+
+ if (deprecation.getReplacement() != null) {
+ builder.append("Replaced by property ").append(deprecation.getReplacement())
+ .append("
");
+ }
}
- } else {
- nodeType = SuggestionNodeType.UNDEFINED;
- }
- }
- return nodeType;
- }
-
- public void refreshDelegate(Module module) {
- if (className != null) {
- // Lets update the delegate information only if anything has changed from last time we saw this
- PsiType type = getPsiType(module);
- boolean validTypeExists = type != null;
- // In the previous refresh, class could not be found. Now class is available in the classpath
- if (validTypeExists) {
- if (delegate == null) {
- delegate = newMetadataProxy(module, type);
- // lets force the nodeType to recalculated
- nodeType = null;
- }
- }
- // In the previous refresh, class was available in classpath. Now it is no longer available
- if (!validTypeExists && delegate != null) {
- delegate = null;
- nodeType = UNKNOWN_CLASS;
- }
- }
- delegateCreationAttempted = true;
- }
-
- @Override
- public int compareTo(@NotNull SpringConfigurationMetadataProperty o) {
- return compare(this, o, comparing(thiz -> thiz.name));
- }
-
- /**
- * @return true if the property is deprecated & level is error, false otherwise
- */
- public boolean isDeprecatedError() {
- return deprecation != null
- && deprecation.getLevel() == SpringConfigurationMetadataDeprecationLevel.error;
- }
-
- public SortedSet findSuggestionsForValues(Module module, FileType fileType,
- List matchesRootTillContainerProperty, String prefix,
- @Nullable Set siblingsToExclude) {
- assert isLeaf(module);
- if (nodeType == VALUES) {
- Collection matches =
- requireNonNull(genericOrKeyHint).findHintValuesWithPrefix(prefix);
- if (!isEmpty(matches)) {
- Stream matchesStream =
- getMatchesAfterExcludingSiblings(genericOrKeyHint, matches, siblingsToExclude);
-
- return matchesStream.map(match -> match
- .buildSuggestionForValue(fileType, matchesRootTillContainerProperty,
- getDefaultValueAsStr(), getPsiType(module))).collect(toCollection(TreeSet::new));
- }
- } else {
- return doWithDelegateOrReturnNull(module, delegate -> delegate
- .findValueSuggestionsForPrefix(module, fileType, matchesRootTillContainerProperty, prefix,
- siblingsToExclude));
+ return builder.toString();
}
- return null;
- }
-
- public void setGenericOrKeyHint(SpringConfigurationMetadataHint genericOrKeyHint) {
- this.genericOrKeyHint = genericOrKeyHint;
- updateNodeType();
- }
-
- public void setValueHint(SpringConfigurationMetadataHint valueHint) {
- this.valueHint = valueHint;
- updateNodeType();
- }
-
- private Stream getMatchesAfterExcludingSiblings(
- @NotNull SpringConfigurationMetadataHint hintFindValueAgainst,
- Collection matches,
- @Nullable Set siblingsToExclude) {
- Stream matchesStream;
- if (siblingsToExclude != null) {
- Set exclusionMembers =
- siblingsToExclude.stream().map(hintFindValueAgainst::findHintValueWithName)
- .collect(toSet());
- matchesStream = matches.stream().filter(value -> !exclusionMembers.contains(value));
- } else {
- matchesStream = matches.stream();
- }
- return matchesStream;
- }
-
- private void updateNodeType() {
- if (isMapWithPredefinedKeys() || isMapWithPredefinedValues()) {
- nodeType = MAP;
- } else if (isLeafWithKnownValues()) {
- nodeType = VALUES;
+ public boolean isLeaf(Module module) {
+ return isLeafWithKnownValues()
+ || getSuggestionNodeType(module).representsLeaf()
+ || doWithDelegateOrReturnDefault(module, metadataProxy -> metadataProxy.isLeaf(module), true);
}
- }
- private PsiType getPsiType(Module module) {
- if (className != null) {
- return safeGetValidType(module, className);
- }
- return null;
- }
-
- private boolean isMapWithPredefinedValues() {
- return valueHint != null && valueHint.representsValueOfMap();
- }
-
- private boolean isMapWithPredefinedKeys() {
- return genericOrKeyHint != null && genericOrKeyHint.representsKeyOfMap();
- }
-
- private boolean isLeafWithKnownValues() {
- return !isMapWithPredefinedKeys() && !isMapWithPredefinedValues() && genericOrKeyHint != null
- && genericOrKeyHint.hasPredefinedValues();
- }
-
- @Contract("_, _, !null -> !null; _, _, null -> null")
- private T doWithDelegateOrReturnDefault(Module module,
- MetadataProxyInvokerWithReturnValue invoker, T defaultValue) {
- MetadataProxy delegate = getDelegate(module);
- if (delegate != null) {
- return invoker.invoke(delegate);
- }
- return defaultValue;
- }
-
- @Nullable
- private T doWithDelegateOrReturnNull(Module module,
- MetadataProxyInvokerWithReturnValue invoker) {
- return doWithDelegateOrReturnDefault(module, invoker, null);
- }
-
- private T doWithMapDelegateOrReturnNull(Module module,
- MetadataProxyInvokerWithReturnValue invoker) {
- MetadataProxy delegate = getDelegate(module);
- if (delegate != null) {
- assert delegate instanceof MapClassMetadataProxy;
- return invoker.invoke(MapClassMetadataProxy.class.cast(delegate));
- }
- return null;
- }
-
- private String getDefaultValueAsStr() {
- if (defaultValue != null && !(defaultValue instanceof Array)
- && !(defaultValue instanceof Collection)) {
- if (className != null && defaultValue instanceof Double) {
- // if defaultValue is a number, its being parsed by gson as double & we will see an incorrect fraction when we take toString()
- switch (className) {
- case "java.lang.Integer":
- return Integer.toString(((Double) defaultValue).intValue());
- case "java.lang.Byte":
- return Byte.toString(((Double) defaultValue).byteValue());
- case "java.lang.Short":
- return Short.toString(((Double) defaultValue).shortValue());
- }
- }
- return defaultValue.toString();
- }
- return null;
- }
+ @NotNull
+ public SuggestionNodeType getSuggestionNodeType(Module module) {
+ if (nodeType == null) {
+ if (className != null) {
+ refreshDelegate(module);
+
+ if (delegate != null) {
+ nodeType = delegate.getSuggestionNodeType(module);
+ }
+
+ if (nodeType == null) {
+ nodeType = UNKNOWN_CLASS;
+ }
+ } else {
+ nodeType = SuggestionNodeType.UNDEFINED;
+ }
+ }
- @Nullable
- private MetadataProxy getDelegate(Module module) {
- if (!delegateCreationAttempted) {
- refreshDelegate(module);
- }
- return delegate;
- }
-
- @Nullable
- private PsiType getMapKeyType(Module module) {
- SuggestionNodeType nodeType = getSuggestionNodeType(module);
- if (nodeType == MAP) {
- return doWithDelegateOrReturnNull(module, delegate -> {
- assert delegate instanceof MapClassMetadataProxy;
- return MapClassMetadataProxy.class.cast(delegate).getMapKeyType(module);
- });
+ return nodeType;
+ }
+
+ public void refreshDelegate(Module module) {
+ if (className != null) {
+ // Lets update the delegate information only if anything has changed from last time we saw this
+ PsiType type = getPsiType(module);
+ boolean validTypeExists = type != null;
+ // In the previous refresh, class could not be found. Now class is available in the classpath
+ if (validTypeExists) {
+ if (delegate == null) {
+ delegate = newMetadataProxy(module, type);
+ // lets force the nodeType to recalculated
+ nodeType = null;
+ }
+ }
+ // In the previous refresh, class was available in classpath. Now it is no longer available
+ if (!validTypeExists && delegate != null) {
+ delegate = null;
+ nodeType = UNKNOWN_CLASS;
+ }
+ }
+ delegateCreationAttempted = true;
}
- return null;
- }
-
- @Nullable
- private PsiType getMapValueType(Module module) {
- SuggestionNodeType nodeType = getSuggestionNodeType(module);
- if (nodeType == MAP) {
- return doWithDelegateOrReturnNull(module, delegate -> {
- assert delegate instanceof MapClassMetadataProxy;
- return MapClassMetadataProxy.class.cast(delegate).getMapValueType(module);
- });
+
+ @Override
+ public int compareTo(@NotNull SpringConfigurationMetadataProperty o) {
+ return compare(this, o, comparing(thiz -> thiz.name));
}
- return null;
- }
-
- public String getDocumentationForValue(Module module, String nodeNavigationPathDotDelimited,
- String value) {
- if (isLeafWithKnownValues()) {
- assert genericOrKeyHint != null;
- SpringConfigurationMetadataHintValue hintValueWithName =
- genericOrKeyHint.findHintValueWithName(value);
- if (hintValueWithName != null) {
- return hintValueWithName
- .getDocumentationForValue(nodeNavigationPathDotDelimited, getMapValueType(module));
- }
- } else {
- // possible this represents an enum
- return doWithDelegateOrReturnNull(module, delegate -> delegate
- .getDocumentationForValue(module, nodeNavigationPathDotDelimited, value));
+
+ /**
+ * @return true if the property is deprecated & level is error, false otherwise
+ */
+ public boolean isDeprecatedError() {
+ return deprecation != null
+ && deprecation.getLevel() == SpringConfigurationMetadataDeprecationLevel.error;
+ }
+
+ public SortedSet findSuggestionsForValues(Module module, FileType fileType,
+ List