|
6 | 6 | package org.mapstruct.intellij.util; |
7 | 7 |
|
8 | 8 | import java.beans.Introspector; |
| 9 | +import java.io.IOException; |
| 10 | +import java.io.InputStream; |
9 | 11 | import java.util.Collections; |
10 | 12 | import java.util.HashMap; |
11 | 13 | import java.util.List; |
12 | 14 | import java.util.Map; |
| 15 | +import java.util.Optional; |
13 | 16 | import java.util.function.Function; |
| 17 | +import java.util.jar.Manifest; |
14 | 18 | import java.util.stream.Stream; |
15 | 19 | import javax.swing.Icon; |
16 | 20 |
|
|
21 | 25 | import com.intellij.openapi.module.ModuleUtilCore; |
22 | 26 | import com.intellij.openapi.roots.ProjectRootManager; |
23 | 27 | import com.intellij.openapi.util.Pair; |
| 28 | +import com.intellij.openapi.util.Version; |
| 29 | +import com.intellij.openapi.vfs.JarFileSystem; |
24 | 30 | import com.intellij.openapi.vfs.VirtualFile; |
25 | 31 | import com.intellij.psi.CommonClassNames; |
26 | 32 | import com.intellij.psi.EmptySubstitutor; |
|
61 | 67 | import org.mapstruct.MappingTarget; |
62 | 68 | import org.mapstruct.Mappings; |
63 | 69 | import org.mapstruct.Named; |
| 70 | +//import org.mapstruct.PrimaryMappingSource; |
64 | 71 | import org.mapstruct.ValueMapping; |
65 | 72 | import org.mapstruct.ValueMappings; |
66 | 73 | import org.mapstruct.factory.Mappers; |
@@ -229,9 +236,15 @@ public boolean isFluentSetter(@NotNull PsiMethod method, PsiType psiType, @NotNu |
229 | 236 | return !psiType.getCanonicalText().startsWith( "java.lang" ) && |
230 | 237 | method.getReturnType() != null && |
231 | 238 | !isAdderWithUpperCase4thCharacter( method ) && |
| 239 | + !isIgnoredRemover( method ) && |
232 | 240 | isAssignableFromReturnTypeOrSuperTypes( psiType, substitutor.substitute( method.getReturnType() ) ); |
233 | 241 | } |
234 | 242 |
|
| 243 | + private static boolean isIgnoredRemover(@NotNull PsiMethod method) { |
| 244 | + return isRemoverWithUpperCase7thCharacter( method ) |
| 245 | + && resolveMapStructProjectVersion( method.getContainingFile() ).isIgnoringRemovers(); |
| 246 | + } |
| 247 | + |
235 | 248 | private static boolean isAssignableFromReturnTypeOrSuperTypes(PsiType psiType, @NotNull PsiType returnType) { |
236 | 249 |
|
237 | 250 | if ( isAssignableFrom( psiType, returnType ) ) { |
@@ -260,6 +273,13 @@ private static boolean isAdderWithUpperCase4thCharacter(@NotNull PsiMethod metho |
260 | 273 | Character.isUpperCase( methodName.charAt( 3 ) ); |
261 | 274 | } |
262 | 275 |
|
| 276 | + private static boolean isRemoverWithUpperCase7thCharacter(@NotNull PsiMethod method) { |
| 277 | + String methodName = method.getName(); |
| 278 | + return methodName.startsWith( "remove" ) && |
| 279 | + methodName.length() > 6 && |
| 280 | + Character.isUpperCase( methodName.charAt( 6 ) ); |
| 281 | + } |
| 282 | + |
263 | 283 | /** |
264 | 284 | * Checks if the {@code method} is a possible builder creation method. |
265 | 285 | * <p> |
@@ -567,7 +587,12 @@ public static MapStructVersion resolveMapStructProjectVersion(@NotNull PsiFile p |
567 | 587 | } |
568 | 588 | return CachedValuesManager.getManager( module.getProject() ).getCachedValue( module, () -> { |
569 | 589 | MapStructVersion mapStructVersion; |
570 | | - if ( JavaPsiFacade.getInstance( module.getProject() ) |
| 590 | + |
| 591 | + Version version = resolveImplementationVersion( module ); |
| 592 | + if ( version != null && version.isOrGreaterThan( 1, 7 ) ) { |
| 593 | + mapStructVersion = MapStructVersion.V1_7_O; |
| 594 | + } |
| 595 | + else if ( JavaPsiFacade.getInstance( module.getProject() ) |
571 | 596 | .findClass( ENUM_MAPPING_ANNOTATION_FQN, module.getModuleRuntimeScope( false ) ) != null ) { |
572 | 597 | mapStructVersion = MapStructVersion.V1_4_O; |
573 | 598 | } |
@@ -659,4 +684,39 @@ public static boolean isInheritInverseConfiguration(PsiMethod method) { |
659 | 684 | return isAnnotated( method, INHERIT_INVERSE_CONFIGURATION_FQN, AnnotationUtil.CHECK_TYPE ); |
660 | 685 | } |
661 | 686 |
|
| 687 | + @Nullable |
| 688 | + private static Version resolveImplementationVersion(Module module) { |
| 689 | + JarFileSystem jarFileSystem = JarFileSystem.getInstance(); |
| 690 | + return Optional.ofNullable( JavaPsiFacade |
| 691 | + .getInstance( module.getProject() ) |
| 692 | + .findClass( MAPPER_ANNOTATION_FQN, module.getModuleRuntimeScope( false ) ) ) |
| 693 | + .map( PsiClass::getContainingFile ) |
| 694 | + .map( PsiFile::getVirtualFile ) |
| 695 | + .map( jarFileSystem::getVirtualFileForJar ) |
| 696 | + .map( jarFileSystem::getJarRootForLocalFile ) |
| 697 | + .map( jarRoot -> jarRoot.findFileByRelativePath( "META-INF/MANIFEST.MF" ) ) |
| 698 | + .map( MapstructUtil::resolveManifest ) |
| 699 | + .map( MapstructUtil::resolveVersionString ) |
| 700 | + .map( Version::parseVersion ) |
| 701 | + .orElse( null ); |
| 702 | + } |
| 703 | + |
| 704 | + private static @Nullable Manifest resolveManifest(VirtualFile manifestFile) { |
| 705 | + try ( InputStream is = manifestFile.getInputStream() ) { |
| 706 | + return new Manifest(is); |
| 707 | + } |
| 708 | + catch ( IOException e ) { |
| 709 | + return null; |
| 710 | + } |
| 711 | + } |
| 712 | + |
| 713 | + private static @Nullable String resolveVersionString(Manifest manifest) { |
| 714 | + if ( manifest.getMainAttributes().containsKey( "Implementation-Version" ) ) { |
| 715 | + return manifest.getMainAttributes().getValue( "Implementation-Version" ); |
| 716 | + } |
| 717 | + else { |
| 718 | + return manifest.getMainAttributes().getValue( "Bundle-Version" ); |
| 719 | + } |
| 720 | + } |
| 721 | + |
662 | 722 | } |
0 commit comments