mapstruct / mapstruct-idea

An IntelliJ IDEA plugin for working with MapStruct
Other
141 stars 38 forks source link

Expression can not get method hint when target uses @Lombok @FieldNameConstants #205

Closed Ben901227 closed 3 months ago

Ben901227 commented 3 months ago

Expected behavior

image When I use a fixed String(modifyDate) to declare the target, I can see the hint in expression getDate() and the default method getDate() is 1 usage.

Actual behavior

image When I use @Lombok @FieldNameConstants define modifyDate to declare the target, I can not see the hint in expression getDate() and the default method getDate() became no usages .

Steps to reproduce the problem

my mapping configuration

    implementation 'org.mapstruct:mapstruct:1.6.0'
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0"
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.6.0'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'

BaseMap

@Mapper
public interface BaseMap {

    BaseMap INSTANCE = Mappers.getMapper( BaseMap.class );

    @Mapping(target = BaseEntity.BaseFields.modifyDate, expression = "java(getDate())")
    BaseDTO toBaseDto(BaseEntity baseEntity);

    default Date getDate() {
        return new Date();
    }
}

BaseDTO

@Data
@FieldNameConstants
public class BaseDTO {
    private Date modifyDate;
}

MapStruct Version

MapStruct 1.6.0

thunderhook commented 3 months ago

Hi @Ben901227, thanks for reaching out!

This is an issue of the mapstruct-idea plugin, so I moved the issue to this repository.

After a quick debugging session it seems that the following IDEA internal class does not resolve the reference:

As far as I know, there is nothing we can do, maybe raise an issue in the IDEA YouTrack itself? @hduelme do you have any idea on how (or if) we can fix this?

This is a one-file-class that can be used to debug:

import java.util.Date;

import lombok.Data;
import lombok.experimental.FieldNameConstants;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
interface Issue205Mapper {

    Issue205Mapper INSTANCE = Mappers.getMapper( Issue205Mapper.class );

    // does not work
    // @Mapping(target = BaseDTO.Fields.modifyDate, expression = "java(getDate())")
    // this works
    @Mapping(target = Source.MODIFY_DATE, expression = "java(getDate())")
    Target toBaseDto(Source baseEntity);

    default Date getDate() {
        return new Date();
    }
}

@Data
class Source {

    public static final String MODIFY_DATE = "modifyDate";

    private Date modifyDate;
}

@Data
@FieldNameConstants
class Target {
    private Date modifyDate;
}
filiphr commented 3 months ago

@thunderhook have you tried with @Mappings(@Mapping(target = BaseDTO.Fields.modifyDate, expression = "java(getDate())")? If you read the docs for FieldNameConstants you'll see that there is a technical limitation and they don't work with MapStruct.

MapStruct interop: When making references to field name constants inside MapStruct's @Mapping, and you use that annotation more than once on a node, you must manually wrap these in the @Mappings 'container annotation'. Like so: @Mappings({@Mapping(target = Entity.Fields.entityProperty, source = "dtoProperty")}).

In any case, I would not spend time on fixing problems with experimental Lombok features such as FieldNameConstants. Therefore, I'm closing this.

Ben901227 commented 3 months ago

Yes, I tried @Mappings(@Mapping(target = BaseDTO.Fields.modifyDate, expression = "java(getDate())") as well, but it's still not working. Thank you for your assistance. I will look for other workarounds.