From 99d20431bda2153182291cfb277601ef347b19bd Mon Sep 17 00:00:00 2001 From: hduelme Date: Sat, 30 Mar 2024 12:37:30 +0100 Subject: [PATCH] Add support for java text-blocks for expression injection --- .../expression/JavaExpressionInjector.java | 3 +- ...essionUnnecessaryWhitespacesInspector.java | 4 ++ .../JavaExpressionInjectionTest.java | 37 +++++++++++ ...onUnnecessaryWhitespacesInspectorTest.java | 14 ++++ ...essionUnnecessaryWhitespacesTextBlock.java | 65 +++++++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 testData/inspection/JavaExpressionUnnecessaryWhitespacesTextBlock.java diff --git a/src/main/java/org/mapstruct/intellij/expression/JavaExpressionInjector.java b/src/main/java/org/mapstruct/intellij/expression/JavaExpressionInjector.java index 8669e25..0469065 100644 --- a/src/main/java/org/mapstruct/intellij/expression/JavaExpressionInjector.java +++ b/src/main/java/org/mapstruct/intellij/expression/JavaExpressionInjector.java @@ -49,7 +49,8 @@ */ public class JavaExpressionInjector implements MultiHostInjector { - public static final Pattern JAVA_EXPRESSION = Pattern.compile( "^\"\\s*java\\((.*)\\)\\s*\"$", Pattern.DOTALL ); + public static final Pattern JAVA_EXPRESSION = Pattern.compile( "^(\"|\"{3})\\s*java\\((.*)\\)\\s*\\1$", + Pattern.DOTALL ); private static final ElementPattern PATTERN = StandardPatterns.or( diff --git a/src/main/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspector.java b/src/main/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspector.java index fe387bd..c91830f 100644 --- a/src/main/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspector.java +++ b/src/main/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspector.java @@ -44,6 +44,10 @@ private void inspectUnnecessaryWhitespaces(@NotNull ProblemsHolder problemsHolde if ( !JAVA_EXPRESSION.matcher( text ).matches() ) { return; } + if ( text.charAt( 1 ) == '"') { + // Text-Block + return; + } if ( text.indexOf( "java(" ) > 1 ) { problemsHolder.registerProblem( property, MapStructBundle.message( "inspection.java.expression.unnecessary.whitespace", diff --git a/src/test/java/org/mapstruct/intellij/expression/JavaExpressionInjectionTest.java b/src/test/java/org/mapstruct/intellij/expression/JavaExpressionInjectionTest.java index 5bdcbdf..ecb8341 100644 --- a/src/test/java/org/mapstruct/intellij/expression/JavaExpressionInjectionTest.java +++ b/src/test/java/org/mapstruct/intellij/expression/JavaExpressionInjectionTest.java @@ -706,6 +706,43 @@ protected void withMapperToDtoWithoutAccessors(String attribute) { assertThat( elementAt.getText() ).isEqualTo( ";" ); } + public void testWithTextBlockAndTargetDefined() { + withTextBlockAndTargetDefined( "expression" ); + withTextBlockAndTargetDefined( "defaultExpression" ); + withTextBlockAndTargetDefined( "conditionExpression" ); + } + + protected void withTextBlockAndTargetDefined(String attribute) { + String mapping = "@Mapping(target = \"manufacturingYear\", " + attribute + + " = \"\"\"\njava(car.)\"\"\")\n"; + @Language("java") + String mapper = formatMapper( CAR_MAPPER, mapping ); + PsiFile file = configureMapperByText( mapper ); + + assertThat( myFixture.completeBasic() ) + .extracting( LookupElementPresentation::renderElement ) + .extracting( LookupElementPresentation::getItemText ) + .contains( + "getMake", + "setMake", + "getManufacturingDate", + "setManufacturingDate", + "getNumberOfSeats", + "setNumberOfSeats" + ); + + assertThat( myFixture.complete( CompletionType.SMART ) ) + .extracting( LookupElementPresentation::renderElement ) + .extracting( LookupElementPresentation::getItemText ) + .containsExactlyInAnyOrder( "getMake", "toString" ); + + PsiElement elementAt = file.findElementAt( myFixture.getCaretOffset() ); + assertThat( elementAt ) + .isNotNull() + .isInstanceOf( PsiJavaToken.class ); + assertThat( elementAt.getText() ).isEqualTo( ";" ); + } + private PsiFile configureMapperByText(@Language("java") String text) { return myFixture.configureByText( JavaFileType.INSTANCE, text ); } diff --git a/src/test/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspectorTest.java b/src/test/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspectorTest.java index 99122e8..3ed2009 100644 --- a/src/test/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspectorTest.java +++ b/src/test/java/org/mapstruct/intellij/inspection/JavaExpressionUnnecessaryWhitespacesInspectorTest.java @@ -7,6 +7,7 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.pom.java.LanguageLevel; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -54,4 +55,17 @@ public void testJavaExpressionUnnecessaryWhitespacesInspectorWhitespaceAfter() { allQuickFixes.forEach( myFixture::launchAction ); myFixture.checkResultByFile( testName + "_after.java" ); } + + //Tests if inspection ignores Textblocks + public void testJavaExpressionUnnecessaryWhitespacesTextBlock() { + doTest(); + String testName = getTestName( false ); + List allQuickFixes = myFixture.getAllQuickFixes(); + assertThat( allQuickFixes ).isEmpty(); + } + + @Override + protected LanguageLevel getLanguageLevel() { + return LanguageLevel.JDK_15; + } } diff --git a/testData/inspection/JavaExpressionUnnecessaryWhitespacesTextBlock.java b/testData/inspection/JavaExpressionUnnecessaryWhitespacesTextBlock.java new file mode 100644 index 0000000..2c40ce8 --- /dev/null +++ b/testData/inspection/JavaExpressionUnnecessaryWhitespacesTextBlock.java @@ -0,0 +1,65 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ + +import org.mapstruct.BeanMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +class Source { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +class Target { + + private String name; + private String lastName; + private String city; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} + +@Mapper +interface SingleMappingMapper { + + @Mapping(target = "name", source = "name", conditionExpression = """ + java( !source.getName().length > 0 ) """) + @Mapping(target = "lastName", source = "name",defaultExpression = """ + java( \" \" ) """) + @Mapping(target = "city", expression = """ + java( \" \" ) """) + Target map(Source source); +} \ No newline at end of file