diff --git a/projects/lsp4mp/projects/maven/config-quickstart/src/main/java/org/acme/config/DefaultValueResource.java b/projects/lsp4mp/projects/maven/config-quickstart/src/main/java/org/acme/config/DefaultValueResource.java index dcf264ce3..f61c36e2b 100644 --- a/projects/lsp4mp/projects/maven/config-quickstart/src/main/java/org/acme/config/DefaultValueResource.java +++ b/projects/lsp4mp/projects/maven/config-quickstart/src/main/java/org/acme/config/DefaultValueResource.java @@ -35,4 +35,16 @@ public class DefaultValueResource { @ConfigProperty(name = "greeting10", defaultValue="AB") char greeting10; + + @ConfigProperty(name = "greeting.optional") // this optional properties are not set + java.util.Optional optional; + + @ConfigProperty(name = "greeting.optional.int") + java.util.OptionalInt optional; + + @ConfigProperty(name = "greeting.optional.long") + java.util.OptionalLong optional; + + @ConfigProperty(name = "greeting.optional.double") + java.util.OptionalDouble optional; } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/config/java/MicroProfileConfigASTValidator.java b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/config/java/MicroProfileConfigASTValidator.java index 1a214ef16..ec5ffe43b 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/config/java/MicroProfileConfigASTValidator.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/internal/config/java/MicroProfileConfigASTValidator.java @@ -115,7 +115,7 @@ public void visitAnnotation(PsiAnnotation annotation) { if (AnnotationUtils.isMatchAnnotation(annotation, CONFIG_PROPERTY_ANNOTATION) && parent != null) { PsiAnnotationMemberValue defaultValueExpr = getAnnotationMemberValueExpression(annotation, MicroProfileConfigConstants.CONFIG_PROPERTY_ANNOTATION_DEFAULT_VALUE); validatePropertyDefaultValue(annotation, defaultValueExpr, parent); - validatePropertyHasValue(annotation, defaultValueExpr); + validatePropertyHasValue(annotation, defaultValueExpr, parent); } } @@ -162,7 +162,7 @@ private void validatePropertyDefaultValue(PsiAnnotation annotation, PsiAnnotatio * @param defaultValueExpr the default value expression, or null if no default * value is defined */ - private void validatePropertyHasValue(PsiAnnotation annotation, PsiAnnotationMemberValue defaultValueExpr) { + private void validatePropertyHasValue(PsiAnnotation annotation, PsiAnnotationMemberValue defaultValueExpr, PsiField parent) { String name = null; PsiAnnotationMemberValue nameExpression = getAnnotationMemberValueExpression(annotation, CONFIG_PROPERTY_ANNOTATION_NAME); @@ -178,7 +178,7 @@ private void validatePropertyHasValue(PsiAnnotation annotation, PsiAnnotationMem String message = MessageFormat.format(EMPTY_KEY_ERROR_MESSAGE, CONFIG_PROPERTY_ANNOTATION_NAME); Diagnostic d = super.addDiagnostic(message, MICRO_PROFILE_CONFIG_DIAGNOSTIC_SOURCE, nameExpression, MicroProfileConfigErrorCode.EMPTY_KEY, DiagnosticSeverity.Error); - } else if (!hasDefaultValue && !doesPropertyHaveValue(name, getContext()) && !isPropertyIgnored(name)) { + } else if (!hasDefaultValue && !doesPropertyHaveValue(name, getContext()) && !isPropertyIgnored(name) && !isOptionalType(parent.getType())) { String message = MessageFormat.format(NO_VALUE_ERROR_MESSAGE, name); Diagnostic d = super.addDiagnostic(message, MICRO_PROFILE_CONFIG_DIAGNOSTIC_SOURCE, nameExpression, MicroProfileConfigErrorCode.NO_VALUE_ASSIGNED_TO_PROPERTY, DiagnosticSeverity.Warning); @@ -282,6 +282,11 @@ private static boolean isAssignable(String typeFqn, String value, Module javaPro } } + private boolean isOptionalType(PsiType fieldBinding) { + // Optional containers: java.util.Optional, java.util.OptionalInt, java.util.OptionalLong, and java.util.OptionalDouble + return TypeConversionUtil.erasure(fieldBinding).getCanonicalText().startsWith("java.util.Optional"); + } + private static boolean doesPropertyHaveValue(String property, JavaDiagnosticsContext context) { Module javaProject = context.getJavaProject(); PsiMicroProfileProject mpProject = PsiMicroProfileProjectManager.getInstance(javaProject.getProject()) diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java index 5c6cd7e7f..02a132568 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/ConfigItemIntBoolDefaultValueTest.java @@ -49,7 +49,8 @@ public void testConfigItemIntBoolDefaultValueTest() throws Exception { assertProperties(infoFromClasspath, 259 + 31 /* properties from Java sources with ConfigProperty */ + // 7 /* static properties from microprofile-context-propagation-api */ + - 1 /* static property from microprofile config_ordinal */, + 1 /* static property from microprofile config_ordinal */ + + 4 /* optional properties */, // GreetingConstructorResource( // @ConfigProperty(name = "greeting.constructor.message") String message, diff --git a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java index c252c743a..0b1003653 100644 --- a/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java +++ b/src/test/java/com/redhat/devtools/intellij/lsp4mp4ij/psi/core/config/properties/MicroProfileConfigPropertyTest.java @@ -45,7 +45,8 @@ public void testConfigQuickstartFromClasspath() throws Exception { 31 /* properties from Java sources with ConfigProperty */ + // 2 /* properties from Java sources with ConfigRoot */ + // 7 /* static properties from microprofile-context-propagation-api */ + - 1 /* static property from microprofile config_ordinal */, + 1 /* static property from microprofile config_ordinal */ + + 4 /* optional properties */, // io.quarkus.deployment.ApplicationConfig p("quarkus-core", "quarkus.application.name", "java.util.Optional", @@ -120,7 +121,8 @@ public void testConfigQuickstartFromJavaSources() throws Exception { MicroProfileProjectInfo infoFromJavaSources = PropertiesManager.getInstance().getMicroProfileProjectInfo(module, MicroProfilePropertiesScope.ONLY_SOURCES, ClasspathKind.SRC, PsiUtilsLSImpl.getInstance(myProject), DocumentFormat.PlainText, new EmptyProgressIndicator()); assertProperties(infoFromJavaSources, 31 /* properties from Java sources with ConfigProperty */ + // - 2 /* properties from Java sources with ConfigRoot */, + 2 /* properties from Java sources with ConfigRoot */ + + 4 /* optional properties */, // GreetingResource // @ConfigProperty(name = "greeting.message")