1515import java .util .List ;
1616import java .util .Map ;
1717import java .util .Objects ;
18+ import java .util .Optional ;
1819import java .util .Set ;
1920import java .util .stream .Stream ;
2021
2122import com .intellij .codeInsight .AnnotationUtil ;
2223import com .intellij .lang .jvm .JvmModifier ;
2324import com .intellij .openapi .util .Pair ;
2425import com .intellij .psi .PsiAnnotation ;
26+ import com .intellij .psi .PsiAnnotationMemberValue ;
2527import com .intellij .psi .PsiClass ;
2628import com .intellij .psi .PsiElement ;
2729import com .intellij .psi .PsiJavaCodeReferenceElement ;
2830import com .intellij .psi .PsiMember ;
2931import com .intellij .psi .PsiMethod ;
32+ import com .intellij .psi .PsiModifierListOwner ;
3033import com .intellij .psi .PsiNameValuePair ;
3134import com .intellij .psi .PsiParameter ;
3235import com .intellij .psi .PsiSubstitutor ;
3639import org .jetbrains .annotations .NotNull ;
3740import org .jetbrains .annotations .Nullable ;
3841
42+ import static com .intellij .codeInsight .AnnotationUtil .findAnnotation ;
43+ import static com .intellij .codeInsight .AnnotationUtil .getBooleanAttributeValue ;
3944import static org .mapstruct .intellij .util .MapstructAnnotationUtils .findAllDefinedMappingAnnotations ;
4045import static org .mapstruct .intellij .util .MapstructUtil .canDescendIntoType ;
4146import static org .mapstruct .intellij .util .MapstructUtil .isFluentSetter ;
@@ -84,13 +89,17 @@ public static PsiType getRelevantType(@NotNull PsiMethod mappingMethod) {
8489 *
8590 * @param psiType to use to extract the accessors
8691 * @param mapStructVersion the MapStruct project version
92+ * @param mappingMethod the mapping method
8793 *
8894 * @return a stream that holds all public write accessors for the given {@code psiType}
8995 */
9096 public static Map <String , Pair <? extends PsiElement , PsiSubstitutor >> publicWriteAccessors (@ NotNull PsiType psiType ,
91- MapStructVersion mapStructVersion ) {
97+ MapStructVersion mapStructVersion , PsiMethod mappingMethod ) {
9298 boolean builderSupportPresent = mapStructVersion .isBuilderSupported ();
93- Pair <PsiClass , TargetType > classAndType = resolveBuilderOrSelfClass ( psiType , builderSupportPresent );
99+ Pair <PsiClass , TargetType > classAndType = resolveBuilderOrSelfClass (
100+ psiType ,
101+ builderSupportPresent && isBuilderEnabled ( mappingMethod )
102+ );
94103 if ( classAndType == null ) {
95104 return Collections .emptyMap ();
96105 }
@@ -111,6 +120,60 @@ public static Map<String, Pair<? extends PsiElement, PsiSubstitutor>> publicWrit
111120 return publicWriteAccessors ;
112121 }
113122
123+ /**
124+ * Whether builder is enabled for the mapping method with the mapstruct version
125+ *
126+ * @param mapStructVersion the MapStruct project version
127+ * @param mappingMethod the mapping method
128+ *
129+ * @return {@code true} if builder can be used for the mapping method
130+ */
131+
132+ public static boolean isBuilderEnabled (MapStructVersion mapStructVersion , PsiMethod mappingMethod ) {
133+ if ( mapStructVersion .isBuilderSupported () ) {
134+ return isBuilderEnabled ( mappingMethod );
135+ }
136+
137+ return false ;
138+ }
139+
140+ /**
141+ * Whether builder is enabled for the mapping method
142+ *
143+ * @param mappingMethod the mapping method
144+ *
145+ * @return {@code true} if builder can be used for the mapping method
146+ */
147+ public static boolean isBuilderEnabled (@ Nullable PsiMethod mappingMethod ) {
148+ Optional <Boolean > disableBuilder = findDisableBuilder ( mappingMethod , MapstructUtil .BEAN_MAPPING_FQN );
149+
150+ if ( !disableBuilder .isPresent () && mappingMethod != null ) {
151+ disableBuilder = findDisableBuilder (
152+ mappingMethod .getContainingClass (),
153+ MapstructUtil .MAPPER_ANNOTATION_FQN
154+ );
155+ }
156+
157+ return !disableBuilder .orElse ( false );
158+ }
159+
160+ private static Optional <Boolean > findDisableBuilder (@ Nullable PsiModifierListOwner listOwner ,
161+ String annotationName ) {
162+ PsiAnnotation requestedAnnotation = findAnnotation ( listOwner , true , annotationName );
163+ if ( requestedAnnotation != null ) {
164+ PsiNameValuePair builderAttribute = AnnotationUtil .findDeclaredAttribute ( requestedAnnotation , "builder" );
165+ if ( builderAttribute != null ) {
166+ PsiAnnotationMemberValue builderValue = builderAttribute .getValue ();
167+ if ( builderValue instanceof PsiAnnotation ) {
168+ Boolean disableBuilder = getBooleanAttributeValue ( (PsiAnnotation ) builderValue , "disableBuilder" );
169+ return Optional .ofNullable ( disableBuilder );
170+ }
171+ }
172+ }
173+
174+ return Optional .empty ();
175+ }
176+
114177 private static Map <String , Pair <PsiParameter , PsiSubstitutor >> constructorParameters (@ NotNull PsiClass psiClass ) {
115178 PsiMethod constructor = resolveMappingConstructor ( psiClass );
116179 if ( constructor == null || !constructor .hasParameters () ) {
@@ -253,19 +316,19 @@ else if ( methodName.startsWith( "set" ) ) {
253316 * Resolve the builder or self class for the {@code psiType}.
254317 *
255318 * @param psiType the type for which the {@link PsiClass} needs to be resolved
256- * @param builderSupportPresent whether MapStruct (1.3) with builder support is present
319+ * @param builderEnabled whether MapStruct (1.3) with builder support is present
257320 *
258321 * @return the pair containing the {@link PsiClass} and the corresponding {@link PsiType}
259322 */
260323 public static Pair <PsiClass , TargetType > resolveBuilderOrSelfClass (@ NotNull PsiType psiType ,
261- boolean builderSupportPresent ) {
324+ boolean builderEnabled ) {
262325 PsiClass psiClass = PsiUtil .resolveClassInType ( psiType );
263326 if ( psiClass == null ) {
264327 return null ;
265328 }
266329 TargetType targetType = TargetType .defaultType ( psiType );
267330
268- if ( builderSupportPresent ) {
331+ if ( builderEnabled ) {
269332 for ( PsiMethod classMethod : psiClass .getMethods () ) {
270333 if ( MapstructUtil .isPossibleBuilderCreationMethod ( classMethod , targetType .type () ) &&
271334 hasBuildMethod ( classMethod .getReturnType (), psiType ) ) {
@@ -357,7 +420,8 @@ public static Stream<String> findAllSourcePropertiesForCurrentTarget(@NotNull Ps
357420 *
358421 * @return all target properties for the given {@code targetClass}
359422 */
360- public static Set <String > findAllTargetProperties (@ NotNull PsiType targetType , MapStructVersion mapStructVersion ) {
361- return publicWriteAccessors ( targetType , mapStructVersion ).keySet ();
423+ public static Set <String > findAllTargetProperties (@ NotNull PsiType targetType , MapStructVersion mapStructVersion ,
424+ PsiMethod mappingMethod ) {
425+ return publicWriteAccessors ( targetType , mapStructVersion , mappingMethod ).keySet ();
362426 }
363427}
0 commit comments