Skip to content

Commit

Permalink
#2185 Fix StackOverflow error when recursive use of mapper in Mapper#…
Browse files Browse the repository at this point in the history
…uses
  • Loading branch information
filiphr committed Aug 29, 2020
1 parent c1feafe commit a9451b1
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
Expand Up @@ -176,11 +176,22 @@ private List<SourceMethod> retrieveMethods(TypeElement usedMapper, TypeElement m
//Add all methods of used mappers in order to reference them in the aggregated model
if ( usedMapper.equals( mapperToImplement ) ) {
for ( DeclaredType mapper : mapperOptions.uses() ) {
methods.addAll( retrieveMethods(
asTypeElement( mapper ),
mapperToImplement,
mapperOptions,
prototypeMethods ) );
TypeElement usesMapperElement = asTypeElement( mapper );
if ( !mapperToImplement.equals( usesMapperElement ) ) {
methods.addAll( retrieveMethods(
usesMapperElement,
mapperToImplement,
mapperOptions,
prototypeMethods ) );
}
else {
messager.printMessage(
mapperToImplement,
mapperOptions.getAnnotationMirror(),
Message.RETRIEVAL_MAPPER_USES_CYCLE,
mapperToImplement
);
}
}
}

Expand Down
Expand Up @@ -149,6 +149,7 @@ public enum Message {
RETRIEVAL_WILDCARD_SUPER_BOUND_SOURCE( "Can't generate mapping method for a wildcard super bound source." ),
RETRIEVAL_WILDCARD_EXTENDS_BOUND_RESULT( "Can't generate mapping method for a wildcard extends bound result." ),
RETRIEVAL_CONTEXT_PARAMS_WITH_SAME_TYPE( "The types of @Context parameters must be unique." ),
RETRIEVAL_MAPPER_USES_CYCLE( "The mapper %s is referenced itself in Mapper#uses.", Diagnostic.Kind.WARNING ),

INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
INHERITINVERSECONFIGURATION_INVALID_NAME( "None of the candidates %s() matches given name: \"%s\"." ),
Expand Down
@@ -0,0 +1,45 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2185;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Filip Hrisafov
*/
@IssueKey("2185")
@RunWith(AnnotationProcessorTestRunner.class)
@WithClasses({
TodoMapper.class
})
public class Issue2185Test {

@Test
@ExpectedCompilationOutcome(value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = TodoMapper.class,
kind = javax.tools.Diagnostic.Kind.WARNING,
line = 14,
message = "The mapper org.mapstruct.ap.test.bugs._2185.TodoMapper is referenced itself in Mapper#uses.")
}
)
public void shouldCompile() {

TodoMapper.TodoResponse response = TodoMapper.INSTANCE.toResponse( new TodoMapper.TodoEntity( "test" ) );

assertThat( response ).isNotNull();
assertThat( response.getNote() ).isEqualTo( "test" );
}
}
@@ -0,0 +1,46 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.test.bugs._2185;

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

/**
* @author Filip Hrisafov
*/
@Mapper(uses = TodoMapper.class)
public interface TodoMapper {

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

TodoResponse toResponse(TodoEntity entity);

class TodoResponse {

private final String note;

public TodoResponse(String note) {
this.note = note;
}

public String getNote() {
return note;
}
}

class TodoEntity {

private final String note;

public TodoEntity(String note) {
this.note = note;
}

public String getNote() {
return note;
}
}
}

0 comments on commit a9451b1

Please sign in to comment.