From 4184d049bd0dcf51db5f268beb1a637abc7d41be Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 13 Dec 2018 17:32:35 -0500 Subject: [PATCH] PT #160496285: Fix Properties TypeUtil to find inner enums in the index --- .../vscode/boot/metadata/types/TypeUtil.java | 51 +++++++++++++++---- .../harness/AbstractPropsEditorTest.java | 10 ++++ .../boot/test/ApplicationYamlEditorTest.java | 20 +++++++- .../src/main/java/demo/FooProperties.java | 12 +++++ 4 files changed, 83 insertions(+), 10 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/types/TypeUtil.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/types/TypeUtil.java index 30e32ca01..37a696bcd 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/types/TypeUtil.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/metadata/types/TypeUtil.java @@ -35,6 +35,8 @@ import java.util.stream.Stream; import javax.inject.Provider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.convert.DurationStyle; import org.springframework.ide.vscode.boot.configurationmetadata.Deprecation; import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents; @@ -57,7 +59,6 @@ import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.CollectionUtil; import org.springframework.ide.vscode.commons.util.EnumValueParser; import org.springframework.ide.vscode.commons.util.LazyProvider; -import org.springframework.ide.vscode.commons.util.Log; import org.springframework.ide.vscode.commons.util.MimeTypes; import org.springframework.ide.vscode.commons.util.Renderables; import org.springframework.ide.vscode.commons.util.StringUtil; @@ -77,6 +78,8 @@ import reactor.core.publisher.Flux; */ public class TypeUtil { + private static final Logger log = LoggerFactory.getLogger(TypeUtil.class); + private static abstract class RadixableParser implements ValueParser { protected abstract Object parse(String str, int radix); @@ -340,7 +343,7 @@ public class TypeUtil { return enums.build(); } } catch (Exception e) { - Log.log(e); + log.error("", e); } } return null; @@ -571,7 +574,7 @@ public class TypeUtil { return eclipseType.isEnum(); } } catch (Exception e) { - Log.log(e); + log.error("", e); } return false; } @@ -579,14 +582,44 @@ public class TypeUtil { private IType findType(String typeName) { try { if (javaProject!=null && typeName!=null) { - return javaProject.findType(typeName); + /* + * Java project expects inner type separator to be '$' while properties index + * has '.' as the separator. Replace '.' with '$' to find inner type + */ + String fqName = switchInnerTypeSeparator(typeName); + return javaProject.findType(fqName); } } catch (Exception e) { - Log.log(e); + log.error("", e); } return null; } + private static String switchInnerTypeSeparator(String name) { + if (name.indexOf('$') < 0) { + boolean foundDeclaringType = false; + String[] tokens = name.split("\\."); + if (tokens.length > 0) { + StringBuilder result = new StringBuilder(); + result.append(tokens[0]); + for (int i = 1; i < tokens.length; i++) { + if (!foundDeclaringType) { + result.append('.'); + result.append(tokens[i]); + if (!tokens[i].isEmpty() && Character.isUpperCase(tokens[i].charAt(0))) { + foundDeclaringType = true; + } + } else { + result.append('$'); + result.append(tokens[i]); + } + } + return result.toString(); + } + } + return name; + } + private IType findType(Type beanType) { return findType(beanType.getErasure()); } @@ -671,7 +704,7 @@ public class TypeUtil { try { propType = Type.fromJavaType(m.getReturnType()); } catch (Exception e) { - Log.log(e); + log.error("", e); } if (beanMode.includesHyphenated()) { properties.add(new TypedProperty(getterOrSetterNameToProperty(m.getElementName()), propType, @@ -782,7 +815,7 @@ public class TypeUtil { } 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); + log.error("", e); return false; } } @@ -794,7 +827,7 @@ public class TypeUtil { } 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); + log.error("", e); return true; } } @@ -852,7 +885,7 @@ public class TypeUtil { IType type = findType(beanType); return type.getMethods().filter(m -> setterName.equals(m.getElementName())).findFirst().orElse(null); } catch (Exception e) { - Log.log(e); + log.error("", e); } return null; } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java index fc2ff12ba..b9880f572 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/editor/harness/AbstractPropsEditorTest.java @@ -181,11 +181,21 @@ public abstract class AbstractPropsEditorTest { } public void assertCompletionsDisplayString(String editorText, String... completionsLabels) throws Exception { + assertCompletionsDisplayString(editorText, false, completionsLabels); + } + + public void assertCompletionsDisplayString(String editorText, boolean includeDetail, String... completionsLabels) throws Exception { Editor editor = newEditor(editorText); List completions = editor.getCompletions(); String[] actualLabels = new String[completions.size()]; for (int i = 0; i < actualLabels.length; i++) { actualLabels[i] = completions.get(i).getLabel(); + if (includeDetail) { + String detail = completions.get(i).getDetail(); + if (detail != null && !detail.isEmpty()) { + actualLabels[i] += " : " + detail; + } + } } assertElements(actualLabels, completionsLabels); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java index bbba03c60..dd2367175 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/test/ApplicationYamlEditorTest.java @@ -1878,7 +1878,22 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest { ); } - @Ignore @Test public void testEnumMapKeyCompletion() throws Exception { + @Test public void testInnerTypeEnumMapKeyCompletion() throws Exception { + useProject(createPredefinedMavenProject("enums-boot-1.3.2-app")); + + data("foo.notes", "java.util.Map", null, "Map weekdays to notes"); + + assertCompletionsDisplayString( + "foo:\n" + + " notes:\n" + + " <*>", + true, + //=> + "monday : String", "tuesday : String", "wednesday : String", "thursday : String", "friday : String", "saturday : String", "sunday : String" + ); + } + + @Test public void testEnumMapKeyCompletion() throws Exception { useProject(createPredefinedMavenProject("enums-boot-1.3.2-app")); data("foo.color-names", "java.util.Map", null, "Map with colors in its keys"); @@ -1909,6 +1924,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest { "foo:\n" + " color-names:\n" + " <*>", + true, //=> "blue : String", "green : String", "red : String" ); @@ -1981,12 +1997,14 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest { "foo:\n" + " color-data:\n" + " <*>", + true, "red : demo.ColorData", "green : demo.ColorData", "blue : demo.ColorData" ); assertCompletionsDisplayString( "foo:\n" + " color-data: <*>\n", + true, "red : demo.ColorData", "green : demo.ColorData", "blue : demo.ColorData" ); diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/FooProperties.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/FooProperties.java index 7046ca45a..47d7d616c 100644 --- a/headless-services/spring-boot-language-server/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/FooProperties.java +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/enums-boot-1.3.2-app/src/main/java/demo/FooProperties.java @@ -9,6 +9,10 @@ import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties("foo") public class FooProperties { + + public enum Weekdays { + MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY + } /** * Pojo @@ -30,6 +34,8 @@ public class FooProperties { //Map Enum -> Pojo private Map colorData; + private Map notes; + //List private List list; @@ -70,4 +76,10 @@ public class FooProperties { public void setList(List list) { this.list = list; } + public Map getNotes() { + return notes; + } + public void setNotes(Map notes) { + this.notes = notes; + } }