diff --git a/.travis.yml b/.travis.yml index 21da563d6..1437875bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,7 @@ before_install: - mkdir -p $HOME/.script - curl https://report.ci/annotate.py -o $HOME/.script/annotate.py --retry 5 - curl https://report.ci/upload.py -o $HOME/.script/upload.py --retry 5 - - curl https://codecov.io/bash -o $HOME/.script/codecov.bash --retry 5 + - curl https://codecov.io/bash -o $HOME/.script/codecov.bash --retry 5 -k - chmod +x $HOME/.script/codecov.bash - chmod +x .travisci/*.sh install: diff --git a/pom.xml b/pom.xml index d367862e7..ecf731f4e 100644 --- a/pom.xml +++ b/pom.xml @@ -327,6 +327,7 @@ org.hamcrest:hamcrest:2.2:jar org.hamcrest:hamcrest:2.1:jar + ch.powerunit.extensions:powerunit-extensions-matchers:0.2.0:jar true ch.powerunit.extensions.matchers diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/pom.xml b/src/it/multimodule-nogeneric-it-jdk8/children/pom.xml index 494834704..585edeb2f 100644 --- a/src/it/multimodule-nogeneric-it-jdk8/children/pom.xml +++ b/src/it/multimodule-nogeneric-it-jdk8/children/pom.xml @@ -69,5 +69,10 @@ powerunit-extensions-matchers-multimodule-parent-it1000 ${project.version} + + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-parent-old-it1000 + ${project.version} + \ No newline at end of file diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java b/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java new file mode 100644 index 000000000..8fa4c8819 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java @@ -0,0 +1,51 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.extensions.matchers.ProvideMatchers; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo24 extends Pojo1 { + + public String msg2; + + public Pojo24() { + } + + public Pojo24(String msg2) { + this.msg2 = msg2; + } + + public Pojo24(String msg1, String msg2) { + super(msg1); + this.msg2 = msg2; + } + + @Override + public String toString() { + return "Pojo24 [msg2=" + msg2 + ", msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java b/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java new file mode 100644 index 000000000..b35b7d79d --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java @@ -0,0 +1,47 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.extensions.matchers.ProvideMatchers; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo26 { + + public Pojo1 field1; + + public Pojo26() { + } + + public Pojo26(Pojo1 field1) { + super(); + this.field1 = field1; + } + + @Override + public String toString() { + return "Pojo26 [field1=" + field1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java new file mode 100644 index 000000000..5d245333a --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java @@ -0,0 +1,96 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.TestDelegate; +import ch.powerunit.TestSuite; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1Matchers; +import ch.powerunit.matchers.MatcherTester; +import static ch.powerunit.matchers.MatcherTester.matcher; +import static ch.powerunit.matchers.MatcherTester.value; + +public class Pojo24MatcherTest implements TestSuite { + + //@formatter:off + @TestDelegate + public final MatcherTester tester = testerOfMatcher(Pojo24Matchers.Pojo24MatcherImpl.class) + .with( + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24With().msg2ContainsString("12")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent ANYTHING]\n[msg2 a string containing \"12\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("12"), + new Pojo24("121")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24With(Pojo1Matchers.pojo1With().msg1("x")).msg2ContainsString("12")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"x\"]\n]\n[msg2 a string containing \"12\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("x","12"), + new Pojo24("x","121")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), + value(new Pojo24("z","11")).withMessage("[parent [msg1 was \"z\"]\n]\n[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("x"))) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is null]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"))) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), + value(new Pojo24("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"),"msg2")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 ANYTHING]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x"), + new Pojo24("y","x2")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo24("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"),"msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"))); + //@formatter:on +} diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java index e7be3d89a..d24a8b8f9 100644 --- a/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java +++ b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java @@ -71,6 +71,27 @@ public class Pojo4MatcherTest implements TestSuite { value("").withMessage("was \"\""), value(new Pojo4()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), value(new Pojo4("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), - value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n"))); + value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo4Matchers.Pojo4MatcherImpl) Pojo4Matchers.pojo4WithSameValue(new Pojo4("y","x"),"msg2")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo4 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 ANYTHING]\n") + .nullRejected("was null") + .accepting( + new Pojo4("y","x"), + new Pojo4("y","x2")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo4()).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo4("11")).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo4Matchers.Pojo4MatcherImpl) Pojo4Matchers.pojo4WithSameValue(new Pojo4("y","x"),"msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo4 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 ANYTHING]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo4("y","x"), + new Pojo4("y2","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo4()).withMessage("[msg2 was null]\n"), + value(new Pojo4("11")).withMessage("[msg2 was \"11\"]\n"))); //@formatter:on } diff --git a/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java index 184a82155..636372f66 100644 --- a/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java +++ b/src/it/multimodule-nogeneric-it-jdk8/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java @@ -70,6 +70,15 @@ public class Pojo6MatcherTest implements TestSuite { value("").withMessage("was \"\""), value(new Pojo6()).withMessage("[field1 was null]\n"), value(new Pojo6(new Pojo1())).withMessage("[field1 [msg1 was null]\n]\n"), - value(new Pojo6(new Pojo1("t"))).withMessage("[field1 [msg1 was \"t\"]\n]\n"))); + value(new Pojo6(new Pojo1("t"))).withMessage("[field1 [msg1 was \"t\"]\n]\n")), + matcher((Pojo6Matchers.Pojo6MatcherImpl) Pojo6Matchers.pojo6WithSameValue(new Pojo6(new Pojo1("a")),"field1.msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo6 with\n[field1 an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 ANYTHING]\n]\n") + .nullRejected("was null") + .accepting( + new Pojo6(new Pojo1("a")), + new Pojo6(new Pojo1("b"))) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo6()).withMessage("[field1 was null]\n"))); //@formatter:on } diff --git a/src/it/multimodule-nogeneric-it-jdk8/parent-old/pom.xml b/src/it/multimodule-nogeneric-it-jdk8/parent-old/pom.xml new file mode 100644 index 000000000..4816c1994 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/parent-old/pom.xml @@ -0,0 +1,68 @@ + + 4.0.0 + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-parent-old-it1000 + + + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-master-it1000 + @project.version@ + ../pom.xml + + + jar + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + jar + + + + + true + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.source.version} + ${java.target.version} + true + + -J@testcompileargs@ + + + + + + + + + org.hamcrest + hamcrest-all + ${hamcrest.version} + + + ch.powerunit + powerunit + ${powerunit.version} + test + + + ch.powerunit.extensions + powerunit-extensions-matchers + 0.2.0 + + + \ No newline at end of file diff --git a/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java b/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java new file mode 100644 index 000000000..2b8387c6b --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java @@ -0,0 +1,45 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.parentold; + +import ch.powerunit.extensions.matchers.ProvideMatchers; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo1 { + + public String msg1; + + public Pojo1() { + } + + public Pojo1(String msg1) { + this.msg1 = msg1; + } + + @Override + public String toString() { + return "Pojo1 [msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java b/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java new file mode 100644 index 000000000..3d3360115 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk8/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java @@ -0,0 +1,42 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.parentold; + +/** + * @author borettim + * + */ +public class Pojo2 { + + public String msg1; + + public Pojo2() { + } + + public Pojo2(String msg1) { + this.msg1 = msg1; + } + + @Override + public String toString() { + return "Pojo2 [msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk8/pom.xml b/src/it/multimodule-nogeneric-it-jdk8/pom.xml index f54929790..dc6beef5c 100644 --- a/src/it/multimodule-nogeneric-it-jdk8/pom.xml +++ b/src/it/multimodule-nogeneric-it-jdk8/pom.xml @@ -162,6 +162,7 @@ parent + parent-old children diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/pom.xml b/src/it/multimodule-nogeneric-it-jdk9+/children/pom.xml index 69112d8b0..d78a1ac28 100644 --- a/src/it/multimodule-nogeneric-it-jdk9+/children/pom.xml +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/pom.xml @@ -69,6 +69,11 @@ powerunit-extensions-matchers-multimodule-parent-it1000 ${project.version} + + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-parent-old-it1000 + ${project.version} + javax.annotation javax.annotation-api diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java b/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java new file mode 100644 index 000000000..8fa4c8819 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo24.java @@ -0,0 +1,51 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.extensions.matchers.ProvideMatchers; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo24 extends Pojo1 { + + public String msg2; + + public Pojo24() { + } + + public Pojo24(String msg2) { + this.msg2 = msg2; + } + + public Pojo24(String msg1, String msg2) { + super(msg1); + this.msg2 = msg2; + } + + @Override + public String toString() { + return "Pojo24 [msg2=" + msg2 + ", msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java b/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java new file mode 100644 index 000000000..b35b7d79d --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/src/main/java/ch/powerunit/extensions/matchers/multi/children/Pojo26.java @@ -0,0 +1,47 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.extensions.matchers.ProvideMatchers; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo26 { + + public Pojo1 field1; + + public Pojo26() { + } + + public Pojo26(Pojo1 field1) { + super(); + this.field1 = field1; + } + + @Override + public String toString() { + return "Pojo26 [field1=" + field1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java new file mode 100644 index 000000000..5d245333a --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo24MatcherTest.java @@ -0,0 +1,96 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.children; + +import ch.powerunit.TestDelegate; +import ch.powerunit.TestSuite; +import ch.powerunit.extensions.matchers.multi.parentold.Pojo1Matchers; +import ch.powerunit.matchers.MatcherTester; +import static ch.powerunit.matchers.MatcherTester.matcher; +import static ch.powerunit.matchers.MatcherTester.value; + +public class Pojo24MatcherTest implements TestSuite { + + //@formatter:off + @TestDelegate + public final MatcherTester tester = testerOfMatcher(Pojo24Matchers.Pojo24MatcherImpl.class) + .with( + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24With().msg2ContainsString("12")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent ANYTHING]\n[msg2 a string containing \"12\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("12"), + new Pojo24("121")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24With(Pojo1Matchers.pojo1With().msg1("x")).msg2ContainsString("12")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"x\"]\n]\n[msg2 a string containing \"12\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("x","12"), + new Pojo24("x","121")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), + value(new Pojo24("z","11")).withMessage("[parent [msg1 was \"z\"]\n]\n[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("x"))) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is null]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[msg2 was \"11\"]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"))) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), + value(new Pojo24("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"),"msg2")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 ANYTHING]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x"), + new Pojo24("y","x2")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo24("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo24Matchers.Pojo24MatcherImpl) Pojo24Matchers.pojo24WithSameValue(new Pojo24("y","x"),"msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo24 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parentold.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo24("y","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo24()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), + value(new Pojo24("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"))); + //@formatter:on +} diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java index e7be3d89a..d24a8b8f9 100644 --- a/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo4MatcherTest.java @@ -71,6 +71,27 @@ public class Pojo4MatcherTest implements TestSuite { value("").withMessage("was \"\""), value(new Pojo4()).withMessage("[parent [msg1 was null]\n]\n[msg2 was null]\n"), value(new Pojo4("11")).withMessage("[parent [msg1 was null]\n]\n[msg2 was \"11\"]\n"), - value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n"))); + value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo4Matchers.Pojo4MatcherImpl) Pojo4Matchers.pojo4WithSameValue(new Pojo4("y","x"),"msg2")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo4 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 is \"y\"]\n]\n[msg2 ANYTHING]\n") + .nullRejected("was null") + .accepting( + new Pojo4("y","x"), + new Pojo4("y","x2")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo4()).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo4("11")).withMessage("[parent [msg1 was null]\n]\n"), + value(new Pojo4("z","x")).withMessage("[parent [msg1 was \"z\"]\n]\n")), + matcher((Pojo4Matchers.Pojo4MatcherImpl) Pojo4Matchers.pojo4WithSameValue(new Pojo4("y","x"),"msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo4 with\n[parent an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 ANYTHING]\n]\n[msg2 is \"x\"]\n") + .nullRejected("was null") + .accepting( + new Pojo4("y","x"), + new Pojo4("y2","x")) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo4()).withMessage("[msg2 was null]\n"), + value(new Pojo4("11")).withMessage("[msg2 was \"11\"]\n"))); //@formatter:on } diff --git a/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java index 184a82155..636372f66 100644 --- a/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java +++ b/src/it/multimodule-nogeneric-it-jdk9+/children/src/test/java/ch/powerunit/extensions/matchers/multi/children/Pojo6MatcherTest.java @@ -70,6 +70,15 @@ public class Pojo6MatcherTest implements TestSuite { value("").withMessage("was \"\""), value(new Pojo6()).withMessage("[field1 was null]\n"), value(new Pojo6(new Pojo1())).withMessage("[field1 [msg1 was null]\n]\n"), - value(new Pojo6(new Pojo1("t"))).withMessage("[field1 [msg1 was \"t\"]\n]\n"))); + value(new Pojo6(new Pojo1("t"))).withMessage("[field1 [msg1 was \"t\"]\n]\n")), + matcher((Pojo6Matchers.Pojo6MatcherImpl) Pojo6Matchers.pojo6WithSameValue(new Pojo6(new Pojo1("a")),"field1.msg1")) + .describedAs("an instance of ch.powerunit.extensions.matchers.multi.children.Pojo6 with\n[field1 an instance of ch.powerunit.extensions.matchers.multi.parent.Pojo1 with\n[msg1 ANYTHING]\n]\n") + .nullRejected("was null") + .accepting( + new Pojo6(new Pojo1("a")), + new Pojo6(new Pojo1("b"))) + .rejecting( + value("").withMessage("was \"\""), + value(new Pojo6()).withMessage("[field1 was null]\n"))); //@formatter:on } diff --git a/src/it/multimodule-nogeneric-it-jdk9+/parent-old/pom.xml b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/pom.xml new file mode 100644 index 000000000..9b17ddbd2 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/pom.xml @@ -0,0 +1,73 @@ + + 4.0.0 + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-parent-old-it1000 + + + ch.powerunit.extensions + powerunit-extensions-matchers-multimodule-master-it1000 + @project.version@ + ../pom.xml + + + jar + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + jar + + + + + true + false + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.source.version} + ${java.target.version} + true + + -J@testcompileargs@ + + + + + + + + + org.hamcrest + hamcrest-all + ${hamcrest.version} + + + ch.powerunit + powerunit + ${powerunit.version} + test + + + ch.powerunit.extensions + powerunit-extensions-matchers + 0.2.0 + + + javax.annotation + javax.annotation-api + 1.3.2 + + + \ No newline at end of file diff --git a/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java new file mode 100644 index 000000000..2b8387c6b --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo1.java @@ -0,0 +1,45 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.parentold; + +import ch.powerunit.extensions.matchers.ProvideMatchers; + +/** + * @author borettim + * + */ +@ProvideMatchers +public class Pojo1 { + + public String msg1; + + public Pojo1() { + } + + public Pojo1(String msg1) { + this.msg1 = msg1; + } + + @Override + public String toString() { + return "Pojo1 [msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java new file mode 100644 index 000000000..3d3360115 --- /dev/null +++ b/src/it/multimodule-nogeneric-it-jdk9+/parent-old/src/main/java/ch/powerunit/extensions/matchers/multi/parentold/Pojo2.java @@ -0,0 +1,42 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.multi.parentold; + +/** + * @author borettim + * + */ +public class Pojo2 { + + public String msg1; + + public Pojo2() { + } + + public Pojo2(String msg1) { + this.msg1 = msg1; + } + + @Override + public String toString() { + return "Pojo2 [msg1=" + msg1 + "]"; + } + +} diff --git a/src/it/multimodule-nogeneric-it-jdk9+/pom.xml b/src/it/multimodule-nogeneric-it-jdk9+/pom.xml index f54929790..dc6beef5c 100644 --- a/src/it/multimodule-nogeneric-it-jdk9+/pom.xml +++ b/src/it/multimodule-nogeneric-it-jdk9+/pom.xml @@ -162,6 +162,7 @@ parent + parent-old children diff --git a/src/main/java/ch/powerunit/extensions/matchers/common/AbstractRoundMirrorSupport.java b/src/main/java/ch/powerunit/extensions/matchers/common/AbstractRoundMirrorSupport.java index 6ba55d010..937788f55 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/common/AbstractRoundMirrorSupport.java +++ b/src/main/java/ch/powerunit/extensions/matchers/common/AbstractRoundMirrorSupport.java @@ -62,9 +62,4 @@ default String getAnnotationProcessorVersion() { return getClass().getPackage().getImplementationVersion(); } - default long getCompatibility() { - // No specify bit for the moment - return 0L; - } - } diff --git a/src/main/java/ch/powerunit/extensions/matchers/common/ListJoining.java b/src/main/java/ch/powerunit/extensions/matchers/common/ListJoining.java index 458f28230..4a5864160 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/common/ListJoining.java +++ b/src/main/java/ch/powerunit/extensions/matchers/common/ListJoining.java @@ -23,7 +23,7 @@ import static java.util.stream.Collectors.joining; import java.util.Arrays; -import java.util.List; +import java.util.Collection; import java.util.Objects; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -107,7 +107,7 @@ public ListJoining(Function mapper, String delimiter, UnaryOperator input) { + public String asString(Collection input) { return Objects.requireNonNull(input, "input can't be null").stream().map(mapper) .collect(collectingAndThen(joining(delimiter), finalizer)); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/common/RessourceLoaderHelper.java b/src/main/java/ch/powerunit/extensions/matchers/common/RessourceLoaderHelper.java new file mode 100644 index 000000000..118827b87 --- /dev/null +++ b/src/main/java/ch/powerunit/extensions/matchers/common/RessourceLoaderHelper.java @@ -0,0 +1,39 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.common; + +import java.util.Scanner; + +public final class RessourceLoaderHelper { + + private RessourceLoaderHelper() { + } + + public static String loadRessource(Class clazz, String ressource) { + try (Scanner s = new Scanner(clazz.getResourceAsStream(ressource))) { + StringBuilder builder = new StringBuilder(); + while (s.hasNext()) { + builder.append(s.nextLine()).append("\n"); + } + return builder.toString(); + } + } + +} diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/Matchable.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/Matchable.java index f07a15266..383f271c5 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/Matchable.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/Matchable.java @@ -28,6 +28,11 @@ public interface Matchable { String getSimpleNameOfGeneratedInterfaceMatcher(); + default long getCompatibility() { + // 0x01 : withSameValue also provides a version to ignore fields + return 0x01; + } + default String getMethodNameDSLWithSameValue() { return getMethodShortClassName() + "WithSameValue"; } @@ -40,7 +45,12 @@ default String getWithSameValue(boolean hasReference) { return getFullyQualifiedNameOfGeneratedClass() + (hasReference ? "::" : ".") + getMethodNameDSLWithSameValue(); } - static Matchable of(String fullName, String methodName, String interfaceName, boolean hasWithSameValue) { + default boolean supportIgnore() { + return (getCompatibility() & 0x01) == 0x01; + } + + static Matchable of(String fullName, String methodName, String interfaceName, boolean hasWithSameValue, + long compatibility) { return new Matchable() { @Override @@ -62,6 +72,11 @@ public String getMethodShortClassName() { public String getFullyQualifiedNameOfGeneratedClass() { return fullName; } + + @Override + public long getCompatibility() { + return compatibility; + } }; } } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitor.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitor.java index 8c0db825c..183c17303 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitor.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitor.java @@ -42,43 +42,8 @@ public NameExtractorVisitor(RoundMirror support) { } @Override - public Optional visitPrimitiveAsBoolean(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "boolean" : "Boolean"); - } - - @Override - public Optional visitPrimitiveAsByte(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "byte" : "Byte"); - } - - @Override - public Optional visitPrimitiveAsShort(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "short" : "Short"); - } - - @Override - public Optional visitPrimitiveAsInt(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "int" : "Integer"); - } - - @Override - public Optional visitPrimitiveAsLong(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "long" : "Long"); - } - - @Override - public Optional visitPrimitiveAsChar(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "char" : "Character"); - } - - @Override - public Optional visitPrimitiveAsFloat(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "float" : "Float"); - } - - @Override - public Optional visitPrimitiveAsDouble(PrimitiveType t, Boolean asPrimitif) { - return of((asPrimitif) ? "double" : "Double"); + public Optional visitPrimitive(PrimitiveType t, Boolean asPrimitif) { + return of(asPrimitif ? t.toString() : getProcessingEnv().getTypeUtils().boxedClass(t).toString()); } @Override diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersAnnotationMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersAnnotationMirror.java index d6254443f..66e383589 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersAnnotationMirror.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersAnnotationMirror.java @@ -60,4 +60,11 @@ public String[] extensions() { return realAnnotation.extensions(); } + /** + * @return the realAnnotation + */ + public ProvideMatchers getRealAnnotation() { + return realAnnotation; + } + } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersMirror.java index 5b06fca2e..433989f83 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersMirror.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvideMatchersMirror.java @@ -20,7 +20,9 @@ package ch.powerunit.extensions.matchers.provideprocessor; import static ch.powerunit.extensions.matchers.common.CommonUtils.asStandardMethodName; +import static java.util.Arrays.stream; import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import java.util.Collection; @@ -38,10 +40,6 @@ public class ProvideMatchersMirror extends ProvideMatchersAnnotationMirror imple private static final String DEFAULT_PARAM_PARENT = " * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n"; - public static final String JAVADOC_WARNING_SYNTAXIC_SUGAR_NO_CHANGE_ANYMORE = "This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore."; - - public static final String JAVADOC_WARNING_PARENT_MAY_BE_VOID = "This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned."; - protected final String simpleNameOfGeneratedClass; protected final String packageNameOfGeneratedClass; protected final String simpleNameOfGeneratedInterfaceMatcher; @@ -102,38 +100,17 @@ private Function asJavadocFormat(String prefix) { } private String paramToJavadoc(Optional param) { - return param.map(asJavadocFormat(" * @param ")).orElse(""); - } - - protected String generateJavaDocWithoutParamNeitherParent(String description, String moreDetails, - Optional param, Optional returnDescription) { - return String.format("/**\n * %1$s.\n *

\n * %2$s\n%3$s%4$s */\n", description, moreDetails, - paramToJavadoc(param), returnDescription.map(asJavadocFormat(" * @return ")).orElse("")); - } - - protected String generateDefaultJavaDoc() { - return String.format("/**\n * %1$s.\n%2$s * \n%3$s * \n */\n", getDefaultDescriptionForDsl(), getParamComment(), - DEFAULT_PARAM_PARENT); + return param.map(p -> stream(p.split("\n"))).map(s -> s.map(asJavadocFormat(" * @param "))) + .map(s -> s.collect(joining())).orElse(""); } - protected String generateDefaultJavaDoc(Optional moreDetails, Optional param, - String returnDescription, boolean withParent) { + public String generateDefaultJavaDoc(Optional moreDetails, Optional param, String returnDescription, + boolean withParent) { return String.format("/**\n * %1$s.\n%2$s%3$s%4$s * \n%5$s * @return %6$s\n */\n", getDefaultDescriptionForDsl(), moreDetails.map(asJavadocFormat(" *

\n * ")).orElse(""), paramToJavadoc(param), getParamComment(), withParent ? DEFAULT_PARAM_PARENT : "", returnDescription); } - protected String generateJavaDoc(String description, boolean withParent) { - return String.format("/**\n * %1$s.\n%2$s * \n%3$s */\n", description, getParamComment(), - withParent ? DEFAULT_PARAM_PARENT : ""); - } - - public String generateMainJavaDoc() { - return String.format( - "/**\n* This class provides matchers for the class {@link %1$s}.\n * \n * @see %1$s The class for which matchers are provided.\n */\n", - getFullyQualifiedNameOfClassAnnotated()); - } - private String getDefaultDescriptionForDsl() { return "Start a DSL matcher for the " + getDefaultLinkForAnnotatedClass(); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementData.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementData.java index b5cf5d690..78556f99b 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementData.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementData.java @@ -23,7 +23,7 @@ @FunctionalInterface public interface ProvidesMatchersAnnotatedElementData extends RoundMirrorSupport { - ProvidesMatchersAnnotatedElementFieldMatcherMirror getFullData(); + ProvidesMatchersAnnotatedElementMatcherMirror getFullData(); default RoundMirror getRoundMirror() { return getFullData().getRoundMirror(); diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementFieldMatcherMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementFieldMatcherMirror.java deleted file mode 100644 index c70d061a6..000000000 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementFieldMatcherMirror.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Powerunit - A JDK1.8 test framework - * Copyright (C) 2014 Mathieu Boretti. - * - * This file is part of Powerunit - * - * Powerunit is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Powerunit is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Powerunit. If not, see . - */ -package ch.powerunit.extensions.matchers.provideprocessor; - -import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.reducing; -import static java.util.stream.Collectors.toList; - -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import javax.lang.model.element.TypeElement; - -import ch.powerunit.extensions.matchers.common.CommonUtils; -import ch.powerunit.extensions.matchers.common.ListJoining; -import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription; -import ch.powerunit.extensions.matchers.provideprocessor.fields.FieldDescriptionMetaData; -import ch.powerunit.extensions.matchers.provideprocessor.fields.IgnoreFieldDescription; - -public abstract class ProvidesMatchersAnnotatedElementFieldMatcherMirror - extends ProvidesMatchersAnnotatedElementGeneralMirror { - - private static final Comparator COMPARING_FIELD_BY_NAME = Comparator - .comparing(FieldDescriptionMetaData::getFieldName); - - private static final String DEFAULT_FEATUREMATCHER_FORCONVERTER = "\n private static <_TARGET,_SOURCE> org.hamcrest.Matcher<_SOURCE> asFeatureMatcher(\n String msg,\n java.util.function.Function<_SOURCE,_TARGET> converter,\n org.hamcrest.Matcher matcher) {\n return new org.hamcrest.FeatureMatcher<_SOURCE,_TARGET>(matcher, msg, msg) {\n protected _TARGET featureValueOf(_SOURCE actual) {\n return converter.apply(actual);\n }};\n }\n\n"; - - protected final List fields; - - private final String fieldsMatcher; - - private static AbstractFieldDescription reduceByOrderingOnIgnoreFieldDescription(AbstractFieldDescription l, - AbstractFieldDescription r) { - return Optional.ofNullable(l).filter(c -> c instanceof IgnoreFieldDescription).orElse(r); - } - - private List generateFields(TypeElement typeElement, - ProvidesMatchersSubElementVisitor providesMatchersSubElementVisitor) { - return typeElement.getEnclosedElements().stream().map(ie -> ie.accept(providesMatchersSubElementVisitor, this)) - .filter(Optional::isPresent).map(Optional::get) - .collect(collectingAndThen(groupingBy(FieldDescriptionMetaData::getFieldName, reducing( - ProvidesMatchersAnnotatedElementFieldMatcherMirror::reduceByOrderingOnIgnoreFieldDescription)), - Map::values)) - .stream().filter(Optional::isPresent).map(Optional::get).sorted(COMPARING_FIELD_BY_NAME) - .collect(toList()); - } - - public ProvidesMatchersAnnotatedElementFieldMatcherMirror(TypeElement typeElement, RoundMirror roundMirror) { - super(typeElement, roundMirror); - this.fields = generateFields(typeElement, new ProvidesMatchersSubElementVisitor(roundMirror)); - this.fieldsMatcher = fields.stream().map(FieldDescriptionMetaData::getMatcherForField) - .map(f -> addPrefix(" ", f)).collect(joining("\n")) + "\n"; - } - - public String generateMatchers() { - return new StringBuilder(DEFAULT_FEATUREMATCHER_FORCONVERTER).append(fieldsMatcher) - .append(fullyQualifiedNameOfSuperClassOfClassAnnotated.map(this::generateParentMatcher).orElse("")) - .toString(); - } - - public String generateParentMatcher(String parent) { - return String.format( - " private static class SuperClassMatcher%1$s extends org.hamcrest.FeatureMatcher<%2$s,%3$s> {\n\n public SuperClassMatcher(org.hamcrest.Matcher matcher) {\n super(matcher,\"parent\",\"parent\");\n }\n\n\n protected %3$s featureValueOf(%2$s actual) {\n return actual;\n }\n\n }\n\n\n", - fullGeneric, getFullyQualifiedNameOfClassAnnotated(), parent); - } - - public String generateMetadata() { - // @formatter:off - return "\n\n" - + " // ---------------------------------------------------------------------------\n" - + " // METADATA\n\n" - + " /**\n" - + " * Metadata regarding this matcher.\n" - + " */\n" - + " public static final Metadata METADATA = new Metadata();\n\n" - +" public static final class FieldMetadata {\n public final String NAME, TYPE, ACCESSOR, STEREOTYPE;\n public final boolean IGNORED;\n private FieldMetadata(String name, String type, String accessor,String stereotype, boolean ignored) {\n NAME=name; TYPE=type; ACCESSOR=accessor; STEREOTYPE=stereotype; IGNORED=ignored;\n }\n }\n\n" - + " public static final class Metadata {\n\n" - + " private Metadata() {}\n\n" - + " public final String ANNOTATION_PROCESSOR_VERSION = \"" + getAnnotationProcessorVersion() + "\";\n\n" - + " public final long COMPATIBILITY = " + getCompatibility() + ";\n\n" - + " public final String SOURCE_CLASS_NAME = \"" + getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric() + "\";\n\n" - + " public final Class<"+getFullyQualifiedNameOfClassAnnotated()+"> SOURCE_CLASS = " + getFullyQualifiedNameOfClassAnnotated() + ".class;\n\n" - + " public final String SOURCE_PARENT_CLASS_NAME = " + fullyQualifiedNameOfSuperClassOfClassAnnotated.map(CommonUtils::toJavaSyntax).orElse("null") + ";\n\n" - + " public final FieldMetadata[] FIELDS = new FieldMetadata[]{ " +ListJoining.joinWithMapperAndDelimiter(f->f.generateMetadata("FieldMetadata"), ", ").asString(fields) + " };\n\n" - + " }\n"; - // @formatter:on - } - -} diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMatcherMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMatcherMirror.java index 5d942b9ee..a41bf7ee1 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMatcherMirror.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMatcherMirror.java @@ -20,185 +20,136 @@ package ch.powerunit.extensions.matchers.provideprocessor; import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix; -import static java.util.stream.Collectors.joining; - -import java.util.Arrays; +import static ch.powerunit.extensions.matchers.common.ListJoining.joinWithMapperAndDelimiter; +import static java.lang.String.format; +import static java.util.Collections.unmodifiableList; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.reducing; +import static java.util.stream.Collectors.toList; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; import java.util.Optional; import javax.lang.model.element.TypeElement; +import ch.powerunit.extensions.matchers.common.CommonUtils; +import ch.powerunit.extensions.matchers.common.ListJoining; +import ch.powerunit.extensions.matchers.common.RessourceLoaderHelper; import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription; +import ch.powerunit.extensions.matchers.provideprocessor.fields.FieldDescriptionMetaData; +import ch.powerunit.extensions.matchers.provideprocessor.fields.IgnoreFieldDescription; +import ch.powerunit.extensions.matchers.provideprocessor.helper.FeatureMatcher; public abstract class ProvidesMatchersAnnotatedElementMatcherMirror - extends ProvidesMatchersAnnotatedElementFieldMatcherMirror { + extends ProvidesMatchersAnnotatedElementGeneralMirror { - private static final String PRIVATE_IMPLEMENTATION_END = "\n\n @Override\n public _PARENT end() {\n return _parentBuilder;\n }\n\n\n"; + private static final String INTERFACE_FORMAT = RessourceLoaderHelper + .loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersInterface.txt"); - private static final String NEXTMATCHERS_DESCRIBETO = " for(org.hamcrest.Matcher nMatcher : nextMatchers) {\n description.appendText(\"[object itself \").appendDescriptionOf(nMatcher).appendText(\"]\\n\");\n }\n }\n"; + private static final String IMPLEMENTATION_NO_PARENT_FORMAT = RessourceLoaderHelper + .loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersImplementationNoParent.txt"); - private static final String PARENT_DESCRIBETO = " description.appendText(\"[\").appendDescriptionOf(_parent).appendText(\"]\\n\");\n"; + private static final String IMPLEMENTATION_PARENT_FORMAT = RessourceLoaderHelper + .loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersImplementationParent.txt"); - private static final String PARENT_VALIDATION = " if(!_parent.matches(actual)) {\n mismatchDescription.appendText(\"[\"); _parent.describeMismatch(actual,mismatchDescription); mismatchDescription.appendText(\"]\\n\");\n result=false;\n }\n"; + private static final String METADATA_FORMAT = RessourceLoaderHelper + .loadRessource(ProvidesMatchersAnnotatedElementMatcherMirror.class, "MatchersMetadata.txt"); - private static final String NEXTMATCHERS_VALIDATION = " for(org.hamcrest.Matcher nMatcher : nextMatchers) {\n if(!nMatcher.matches(actual)) {\n mismatchDescription.appendText(\"[object itself \"); nMatcher.describeMismatch(actual,mismatchDescription); mismatchDescription.appendText(\"]\\n\");\n result=false;\n }\n }\n return result;\n }\n\n"; + private static final ListJoining JOIN_FIELD_DSL_INTERFACE = joinWithMapperAndDelimiter( + s -> addPrefix(" ", s.getDslInterface()), "\n"); - private static final String JAVADOC_ANDWITHAS = " /**\n * Add a matcher on the object itself and not on a specific field, but convert the object before passing it to the matcher.\n *

\n * This method, when used more than once, just add more matcher to the list.\n * @param converter the function to convert the object.\n * @param otherMatcher the matcher on the converter object itself.\n * @param <_TARGETOBJECT> the type of the target object\n * @return the DSL to continue\n */\n"; + private static final ListJoining JOIN_FIELD_MATCHERFIELD = joinWithMapperAndDelimiter( + s -> addPrefix(" ", s.asMatcherField()), "\n"); - private static final String JAVADOC_ANDWITH = " /**\n * Add a matcher on the object itself and not on a specific field.\n *

\n * This method, when used more than once, just add more matcher to the list.\n * @param otherMatcher the matcher on the object itself.\n * @return the DSL to continue\n */\n"; + private static final ListJoining JOIN_FIELD_IMPL = joinWithMapperAndDelimiter( + s -> addPrefix(" ", s.getImplementationInterface()), "\n"); - private final String dslInterfaceDescription; + private static final ListJoining JOIN_FIELD_MATCHES_SAFELY = joinWithMapperAndDelimiter( + s -> addPrefix(" ", s.asMatchesSafely() + "\n"), "\n"); - public ProvidesMatchersAnnotatedElementMatcherMirror(TypeElement typeElement, RoundMirror roundMirror) { - super(typeElement, roundMirror); - this.dslInterfaceDescription = "DSL interface for matcher on " + getDefaultLinkForAnnotatedClass(); - } + private static final ListJoining JOIN_FIELD_DESCRIBE_TO = joinWithMapperAndDelimiter( + s -> addPrefix(" ", s.asDescribeTo() + "\n"), "\n"); - public String generatePublicInterface() { - return new StringBuilder().append(generateMainBuildPublicInterface()) - .append(generateMainParentPublicInterface()).append(generateExposedPublicInterface()).toString(); + private static final ListJoining JOIN_FIELD_MATCHER = joinWithMapperAndDelimiter( + f -> addPrefix(" ", f.getMatcherForField()), "\n"); - } + private static final ListJoining JOIN_FIELD_METADATA = joinWithMapperAndDelimiter( + f -> f.generateMetadata("FieldMetadata"), ", "); - private String generateExposedPublicInterface() { - String simpleName = simpleNameOfGeneratedInterfaceMatcher; - return new StringBuilder(addPrefix(" ", generateDefaultJavaDoc())).append("\n") - .append(" public static interface ").append(simpleName).append(getFullGenericParent()) - .append(" extends org.hamcrest.Matcher<") - .append(getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric()).append(">,") - .append(simpleName).append("BuildSyntaxicSugar ").append(generic).append(",").append(simpleName) - .append("EndSyntaxicSugar ").append(getGenericParent()).append(" {\n") - .append(fields.stream().map(AbstractFieldDescription::getDslInterface).map(s -> addPrefix(" ", s)) - .collect(joining("\n"))) - .append("\n\n").append(generateAsPublicInterface()).append(" }\n").toString(); - } + private static final Comparator COMPARING_FIELD_BY_NAME = Comparator + .comparing(FieldDescriptionMetaData::getFieldName); + + private static final String DEFAULT_FEATUREMATCHER_FORCONVERTER = "\n private static <_TARGET,_SOURCE> org.hamcrest.Matcher<_SOURCE> asFeatureMatcher(\n String msg,\n java.util.function.Function<_SOURCE,_TARGET> converter,\n org.hamcrest.Matcher matcher) {\n return new org.hamcrest.FeatureMatcher<_SOURCE,_TARGET>(matcher, msg, msg) {\n protected _TARGET featureValueOf(_SOURCE actual) {\n return converter.apply(actual);\n }};\n }\n\n"; - private String generateAsPublicInterface() { - String fully = getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(); - String otherMatcher = "org.hamcrest.Matcher otherMatcher"; - String interfaceWithGeneric = getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent(); - - StringBuilder sb = new StringBuilder(JAVADOC_ANDWITH).append(" ").append(interfaceWithGeneric) - .append(" andWith(").append(otherMatcher).append(");\n\n"); - - sb.append(JAVADOC_ANDWITHAS).append(String.format( - " default <_TARGETOBJECT> %1$s andWithAs(java.util.function.Function<%2$s,_TARGETOBJECT> converter,org.hamcrest.Matcher otherMatcher) {\n return andWith(asFeatureMatcher(\" \",converter,otherMatcher));\n }\n\n", - interfaceWithGeneric, fully)); - - sb.append(addPrefix(" ", - generateJavaDocWithoutParamNeitherParent( - "Method that return the matcher itself and accept one single Matcher on the object itself.", - JAVADOC_WARNING_SYNTAXIC_SUGAR_NO_CHANGE_ANYMORE, - Optional.of("otherMatcher the matcher on the object itself."), Optional.of("the matcher")))) - .append(String.format( - "\n default org.hamcrest.Matcher<%1$s> buildWith(%2$s) {\n return andWith(otherMatcher);\n }\n\n", - fully, otherMatcher)); - - sb.append(addPrefix(" ", generateJavaDocWithoutParamNeitherParent( - "Method that return the parent builder and accept one single Matcher on the object itself.", - JAVADOC_WARNING_PARENT_MAY_BE_VOID, Optional.of("otherMatcher the matcher on the object itself."), - Optional.of("the parent builder or null if not applicable")))) - .append(String.format( - " default _PARENT endWith(%1$s){\n return andWith(otherMatcher).end();\n }\n", - otherMatcher)); - return sb.toString(); + protected final List fields; + + private final String fieldsMatcher; + + private static AbstractFieldDescription reduceByOrderingOnIgnoreFieldDescription(AbstractFieldDescription l, + AbstractFieldDescription r) { + return Optional.ofNullable(l).filter(c -> c instanceof IgnoreFieldDescription).orElse(r); } - private String generateMainParentPublicInterface() { - StringBuilder sb = new StringBuilder(); - sb.append( - addPrefix(" ", generateJavaDoc(dslInterfaceDescription + " to support the end syntaxic sugar", true))) - .append("\n"); - sb.append(" public static interface " + simpleNameOfGeneratedInterfaceMatcher + "EndSyntaxicSugar" - + getFullGenericParent() + " extends org.hamcrest.Matcher<" - + getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric() + "> {\n"); - sb.append(addPrefix(" ", - generateJavaDocWithoutParamNeitherParent("Method that return the parent builder", - JAVADOC_WARNING_PARENT_MAY_BE_VOID, Optional.empty(), - Optional.of("the parent builder or null if not applicable")))) - .append("\n _PARENT end();\n }\n"); - return sb.toString(); + private List generateFields(TypeElement typeElement, + ProvidesMatchersSubElementVisitor providesMatchersSubElementVisitor) { + return typeElement.getEnclosedElements().stream().map(ie -> ie.accept(providesMatchersSubElementVisitor, this)) + .filter(Optional::isPresent).map(Optional::get) + .collect(collectingAndThen(groupingBy(FieldDescriptionMetaData::getFieldName, reducing( + ProvidesMatchersAnnotatedElementMatcherMirror::reduceByOrderingOnIgnoreFieldDescription)), + Map::values)) + .stream().filter(Optional::isPresent).map(Optional::get).sorted(COMPARING_FIELD_BY_NAME) + .collect(toList()); } - private String generateMainBuildPublicInterface() { - String fullyWithGeneric = getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(); - return new StringBuilder(addPrefix(" ", - generateJavaDoc(dslInterfaceDescription + " to support the build syntaxic sugar", false))) - .append("\n public static interface ").append(simpleNameOfGeneratedInterfaceMatcher) - .append("BuildSyntaxicSugar").append(fullGeneric).append(" extends org.hamcrest.Matcher<") - .append(fullyWithGeneric).append("> {\n") - .append(addPrefix(" ", - generateJavaDocWithoutParamNeitherParent("Method that return the matcher itself.", - JAVADOC_WARNING_SYNTAXIC_SUGAR_NO_CHANGE_ANYMORE, Optional.empty(), - Optional.of("the matcher")))) - .append("\n default org.hamcrest.Matcher<").append(fullyWithGeneric) - .append("> build() {\n return this;\n }\n }\n").toString(); + public ProvidesMatchersAnnotatedElementMatcherMirror(TypeElement typeElement, RoundMirror roundMirror) { + super(typeElement, roundMirror); + this.fields = unmodifiableList(generateFields(typeElement, new ProvidesMatchersSubElementVisitor(roundMirror))); + this.fieldsMatcher = JOIN_FIELD_MATCHER.asString(fields) + "\n"; } - public String generatePrivateImplementationConstructor(String argument, String... body) { - return String.format(" public %1$s(%2$s) {\n%3$s\n }", getSimpleNameOfGeneratedImplementationMatcher(), - argument, Arrays.stream(body).map(l -> " " + l).collect(joining("\n"))); + public String generatePublicInterface() { + return addPrefix(" ", + format(INTERFACE_FORMAT, getFullyQualifiedNameOfClassAnnotated(), getSimpleNameOfClassAnnotated(), + getParamComment(), simpleNameOfGeneratedInterfaceMatcher, fullGeneric, + getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), getFullGenericParent(), + generic, getGenericParent(), JOIN_FIELD_DSL_INTERFACE.asString(fields))); } protected String generatePrivateImplementation() { - return new StringBuilder(" /* package protected */ static class ") - .append(getSimpleNameOfGeneratedImplementationMatcher()).append(getFullGenericParent()) - .append(" extends org.hamcrest.TypeSafeDiagnosingMatcher<") - .append(getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric()).append("> implements ") - .append(getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent() + " {\n ") - .append(fields.stream().map(AbstractFieldDescription::asMatcherField).collect(joining("\n "))) - .append("\n private final _PARENT _parentBuilder;\n\n private final java.util.List nextMatchers = new java.util.ArrayList<>();\n") - .append(generateParentEntry()) - .append(fields.stream().map(AbstractFieldDescription::getImplementationInterface) - .map(s -> addPrefix(" ", s)).collect(joining("\n"))) - .append("\n").append(generatePrivateImplementationForMatchersSafely()).append("\n") - .append(generatedPrivateImplementationForDescribeTo()).append(PRIVATE_IMPLEMENTATION_END) - .append(generatePrivateImplementationForAndWith()).append("\n }\n").toString(); + return addPrefix(" ", format(hasSuperClass() ? IMPLEMENTATION_PARENT_FORMAT : IMPLEMENTATION_NO_PARENT_FORMAT, + getSimpleNameOfGeneratedImplementationMatcher(), getFullGenericParent(), + getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), + getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent(), getFullyQualifiedNameOfClassAnnotated(), + JOIN_FIELD_MATCHERFIELD.asString(fields), JOIN_FIELD_IMPL.asString(fields), + JOIN_FIELD_MATCHES_SAFELY.asString(fields), JOIN_FIELD_DESCRIBE_TO.asString(fields), + fullyQualifiedNameOfSuperClassOfClassAnnotated.orElse(""))); + } - private String generateParentEntry() { - return fullyQualifiedNameOfSuperClassOfClassAnnotated - .map(p -> " private SuperClassMatcher _parent;\n\n" - + generatePrivateImplementationConstructor("org.hamcrest.Matcher parent", - "this._parent=new SuperClassMatcher(parent);", "this._parentBuilder=null;") - + "\n\n" - + generatePrivateImplementationConstructor( - "org.hamcrest.Matcher parent,_PARENT parentBuilder", - "this._parent=new SuperClassMatcher(parent);", "this._parentBuilder=parentBuilder;") - + "\n\n") - .orElseGet(() -> generatePrivateImplementationConstructor("", "this._parentBuilder=null;") + "\n\n" - + generatePrivateImplementationConstructor("_PARENT parentBuilder", - "this._parentBuilder=parentBuilder;") - + "\n\n"); + public String generateMatchers() { + return new StringBuilder(DEFAULT_FEATUREMATCHER_FORCONVERTER).append(fieldsMatcher) + .append(fullyQualifiedNameOfSuperClassOfClassAnnotated.map(this::generateParentMatcher).orElse("")) + .toString(); } - private String generatePrivateImplementationForMatchersSafely() { - StringBuilder sb = new StringBuilder(String.format( - " @Override\n protected boolean matchesSafely(%1$s actual, org.hamcrest.Description mismatchDescription) {\n boolean result=true;\n", - getFullyQualifiedNameOfClassAnnotated())); - if (hasSuperClass()) { - sb.append(PARENT_VALIDATION); - } - fields.stream().map(f -> addPrefix(" ", f.asMatchesSafely() + "\n")).forEach(sb::append); - sb.append(NEXTMATCHERS_VALIDATION); - return sb.toString(); + public String generateParentMatcher(String parent) { + return addPrefix(" ", new FeatureMatcher("SuperClass", fullGeneric, getFullyQualifiedNameOfClassAnnotated(), + "", parent, "parent", "actual").toString()); } - private String generatedPrivateImplementationForDescribeTo() { - StringBuilder sb = new StringBuilder(String.format( - " @Override\n public void describeTo(org.hamcrest.Description description) {\n description.appendText(\"an instance of %1$s with\\n\");\n", - getFullyQualifiedNameOfClassAnnotated())); - if (hasSuperClass()) { - sb.append(PARENT_DESCRIBETO); - } - fields.stream().map(f -> addPrefix(" ", f.asDescribeTo() + "\n")).forEach(sb::append); - sb.append(NEXTMATCHERS_DESCRIBETO); - return sb.toString(); + public List getFields() { + return fields; } - private String generatePrivateImplementationForAndWith() { - return String.format( - " @Override\n public %1$s andWith(org.hamcrest.Matcher otherMatcher) {\n nextMatchers.add(java.util.Objects.requireNonNull(otherMatcher,\"A matcher is expected\"));\n return this;\n }\n", - getSimpleNameOfGeneratedInterfaceMatcherWithGenericParent(), - getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric()); + public String generateMetadata() { + return format(METADATA_FORMAT, getAnnotationProcessorVersion(), getCompatibility(), + getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), + getFullyQualifiedNameOfClassAnnotated(), + fullyQualifiedNameOfSuperClassOfClassAnnotated.map(CommonUtils::toJavaSyntax).orElse("null"), + JOIN_FIELD_METADATA.asString(fields)); } + } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirror.java index 168c803be..d23d70b6c 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirror.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirror.java @@ -25,6 +25,8 @@ import static ch.powerunit.extensions.matchers.common.FileObjectHelper.processFileWithIOExceptionAndResult; import static ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod.of; import static java.util.Collections.unmodifiableList; +import static java.util.Optional.empty; +import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; import java.io.PrintWriter; @@ -32,39 +34,45 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Formatter; import java.util.List; -import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic.Kind; +import ch.powerunit.extensions.matchers.common.ListJoining; +import ch.powerunit.extensions.matchers.common.RessourceLoaderHelper; import ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod; +import ch.powerunit.extensions.matchers.provideprocessor.helper.ProvidesMatchersWithSameValueHelper; public class ProvidesMatchersAnnotatedElementMirror extends ProvidesMatchersAnnotatedElementMatcherMirror { private final Collection> dslProvider; + private static final String MATCHER_FORMAT = RessourceLoaderHelper + .loadRessource(ProvidesMatchersAnnotatedElementMirror.class, "Matchers.txt"); + + private static final ListJoining JOIN_DSL_METHOD = ListJoining + .joinWithMapperAndDelimiter(m -> addPrefix(" ", m.asStaticImplementation()), "\n"); + public ProvidesMatchersAnnotatedElementMirror(TypeElement typeElement, RoundMirror roundMirror) { super(typeElement, roundMirror); List> tmp = new ArrayList<>( Arrays.asList(this::generateDefaultDSLStarter, this::generateDefaultForChainingDSLStarter)); if (hasSuperClass()) { tmp.add(this::generateParentDSLStarter); - tmp.add(this::generateParentValueDSLStarter); + tmp.addAll(ProvidesMatchersWithSameValueHelper.generateParentValueDSLStarter(this)); if (((TypeElement) roundMirror.getTypeUtils().asElement(element.getSuperclass())).getTypeParameters() .isEmpty()) { tmp.add(this::generateParentInSameRoundWithChaningDSLStarter); } } else { - tmp.add(() -> generatParentValueDSLStarter("")); + tmp.addAll(ProvidesMatchersWithSameValueHelper.generateNoParentValueDSLStarter(this)); } - tmp.addAll(Optional.ofNullable(getDSLExtension()).orElseGet(Collections::emptyList).stream() + tmp.addAll(ofNullable(getDSLExtension()).orElseGet(Collections::emptyList).stream() .map(t -> t.getDSLMethodFor(() -> this)).flatMap(Collection::stream).collect(toList())); tmp.addAll(roundMirror.getDSLMethodFor(() -> this)); this.dslProvider = unmodifiableList(tmp); @@ -72,26 +80,16 @@ public ProvidesMatchersAnnotatedElementMirror(TypeElement typeElement, RoundMirr public Collection process() { Element te = element; - String simpleName = getSimpleNameOfGeneratedClass(); return processFileWithIOExceptionAndResult( () -> getFiler().createSourceFile(getFullyQualifiedNameOfGeneratedClass(), te), - jfo -> new PrintWriter(jfo.openWriter()), wjfo -> { - wjfo.println("package " + getPackageNameOfGeneratedClass() + ";\n"); - wjfo.println(generateMainJavaDoc()); - wjfo.println(generateGeneratedAnnotation(ProvidesMatchersAnnotationsProcessor.class, comments())); - wjfo.println("public final class " + simpleName + " {\n"); - wjfo.println(" private " + simpleName + "() {}\n"); - wjfo.println(generateMatchers()); - wjfo.println(); - wjfo.println(generatePublicInterface()); - wjfo.println(); - wjfo.println(generatePrivateImplementation()); - wjfo.println(); + jfo -> new Formatter(new PrintWriter(jfo.openWriter())), output -> { Collection tmp = generateDSLStarter(); - tmp.stream().map(m -> addPrefix(" ", m.asStaticImplementation())).forEach(wjfo::println); - wjfo.println(); - wjfo.println(generateMetadata()); - wjfo.println("}"); + output.format(MATCHER_FORMAT, getPackageNameOfGeneratedClass(), + getFullyQualifiedNameOfClassAnnotated(), + generateGeneratedAnnotation(ProvidesMatchersAnnotationsProcessor.class, comments()), + getSimpleNameOfGeneratedClass(), generateMatchers(), generatePublicInterface(), + generatePrivateImplementation(), JOIN_DSL_METHOD.asString(tmp), generateMetadata()); + output.flush(); return tmp; }, e -> traceErrorAndDump(this, e, te)); } @@ -104,13 +102,8 @@ public String getDefaultStarterBody(boolean withParentBuilder) { String targetImpl = withParentBuilder ? getSimpleNameOfGeneratedImplementationMatcherWithGenericParent() : getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent(); boolean withSuper = hasSuperClass(); - if (withParentBuilder) { - return withSuper ? ("return new " + targetImpl + "(org.hamcrest.Matchers.anything(),parentBuilder);") - : ("return new " + targetImpl + "(parentBuilder);"); - } else { - return withSuper ? ("return new " + targetImpl + "(org.hamcrest.Matchers.anything());") - : ("return new " + targetImpl + "();"); - } + return "return new " + targetImpl + "(" + (withSuper ? "org.hamcrest.Matchers.anything()" : "") + + (withSuper && withParentBuilder ? "," : "") + (withParentBuilder ? "parentBuilder" : "") + ");"; } public String generateDefaultJavaDocWithDSLStarter(Optional param, String returnDescription, @@ -120,17 +113,17 @@ public String generateDefaultJavaDocWithDSLStarter(Optional param, Strin public String generateDefaultJavaDocWithoutDSLStarter(Optional param, String returnDescription, boolean withParent) { - return generateDefaultJavaDoc(Optional.empty(), param, returnDescription, withParent); + return generateDefaultJavaDoc(empty(), param, returnDescription, withParent); } public DSLMethod generateDefaultDSLStarter() { return of(fullGeneric + " " + getFullyQualifiedNameOfGeneratedClass() + "." + getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent() + " " + methodShortClassName + "With") .withImplementation(getDefaultStarterBody(false)) - .withJavadoc(generateDefaultJavaDocWithDSLStarter(Optional.empty(), "the DSL matcher", false)); + .withJavadoc(generateDefaultJavaDocWithDSLStarter(empty(), "the DSL matcher", false)); } - private String getJavadocForDSLStarter() { + public String getJavadocForDSLStarter() { return "The returned builder (which is also a Matcher), at this point accepts any object that is a " + getDefaultLinkForAnnotatedClass() + "."; } @@ -158,42 +151,6 @@ public DSLMethod generateParentDSLStarter() { false)); } - public DSLMethod generatParentValueDSLStarter(String argumentForParentBuilder) { - String genericNoParent = getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent(); - String javadoc = generateDefaultJavaDocWithoutDSLStarter( - Optional.of("other the other object to be used as a reference."), "the DSL matcher", false); - List lines = new ArrayList<>(); - lines.add(genericNoParent + " m=new " + getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent() + "(" - + argumentForParentBuilder + ");"); - lines.addAll(fields.stream().map(f -> f.getFieldCopy("m", "other") + ";").collect(toList())); - lines.add("return m;"); - return of(fullGeneric + " " + getFullyQualifiedNameOfGeneratedClass() + "." + genericNoParent + " " - + getMethodNameDSLWithSameValue()) - .withOneArgument(getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), "other") - .withImplementation(lines).withJavadoc(javadoc); - } - - public DSLMethod generateParentValueDSLStarterWeak() { - if (realAnnotation.allowWeakWithSameValue()) { - Optional am = getAnnotationMirror(); - Optional av = am.map(a -> a.getElementValues().entrySet().stream() - .filter(kv -> kv.getKey().getSimpleName().toString().equals("allowWeakWithSameValue")) - .map(Entry::getValue).findAny().orElse(null)); - getMessager().printMessage(Kind.MANDATORY_WARNING, - "This class use the option allowWeakWithSameValue and a weak WithSameValue is detected. The generated WithSameValue DSL may not be able to fully control all the field of this class", - element, am.orElse(null), av.orElse(null)); - - return generatParentValueDSLStarter("org.hamcrest.Matchers.anything()"); - } - return null; - } - - public DSLMethod generateParentValueDSLStarter() { - return getParentMirror() - .map(parentMirror -> generatParentValueDSLStarter(parentMirror.getWithSameValue(false) + "(other)")) - .orElse(generateParentValueDSLStarterWeak()); - } - public DSLMethod generateParentInSameRoundWithChaningDSLStarter() { String implGenericNoParent = getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent(); return getParentMirror().map(parentMirror -> { @@ -207,8 +164,7 @@ public DSLMethod generateParentInSameRoundWithChaningDSLStarter() { pmfqngc + "." + parentSimpleName + " tmp = " + pmfqngc + "." + parentMirror.getMethodNameDSLWithParent() + "(m);", "m._parent = new SuperClassMatcher(tmp);", "return tmp;") - .withJavadoc(generateDefaultJavaDoc(Optional.empty(), Optional.empty(), "the DSL matcher", - false)); + .withJavadoc(generateDefaultJavaDoc(empty(), empty(), "the DSL matcher", false)); }).orElse(null); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersSubElementVisitor.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersSubElementVisitor.java index 529e93da5..21da9fbe2 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersSubElementVisitor.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersSubElementVisitor.java @@ -39,7 +39,7 @@ * */ public class ProvidesMatchersSubElementVisitor extends - AbstractSimpleElementVisitor, ProvidesMatchersAnnotatedElementFieldMatcherMirror, RoundMirror> { + AbstractSimpleElementVisitor, ProvidesMatchersAnnotatedElementMatcherMirror, RoundMirror> { private final Function removeFromIgnoreList; private final NameExtractorVisitor extractNameVisitor; @@ -58,7 +58,7 @@ public Optional removeIfNeededAndThenReturn( @Override public Optional visitVariable(VariableElement e, - ProvidesMatchersAnnotatedElementFieldMatcherMirror p) { + ProvidesMatchersAnnotatedElementMatcherMirror p) { if (isPublic(e) && !isStatic(e)) { String fieldName = getSimpleName(e); return createFieldDescriptionIfApplicableAndRemoveElementFromListWhenApplicable(e, p, fieldName); @@ -69,7 +69,7 @@ public Optional visitVariable(VariableElement e, @Override public Optional visitExecutable(ExecutableElement e, - ProvidesMatchersAnnotatedElementFieldMatcherMirror p) { + ProvidesMatchersAnnotatedElementMatcherMirror p) { if (isPublic(e) && e.getParameters().size() == 0 && !isStatic(e)) { String simpleName = getSimpleName(e); if (simpleName.matches("^((get)|(is)).*")) { @@ -91,15 +91,13 @@ private void generateIfNeededErrorForNotSupportedElementAndRemoveIt(String descr } private Optional visiteExecutableGet(ExecutableElement e, String prefix, - ProvidesMatchersAnnotatedElementFieldMatcherMirror p) { - String methodName = getSimpleName(e); - String fieldNameDirect = methodName.replaceFirst(prefix, ""); - String fieldName = asStandardMethodName(fieldNameDirect); - return createFieldDescriptionIfApplicableAndRemoveElementFromListWhenApplicable(e, p, fieldName); + ProvidesMatchersAnnotatedElementMatcherMirror p) { + return createFieldDescriptionIfApplicableAndRemoveElementFromListWhenApplicable(e, p, + asStandardMethodName(getSimpleName(e).replaceFirst(prefix, ""))); } public Optional createFieldDescriptionIfApplicableAndRemoveElementFromListWhenApplicable( - Element e, ProvidesMatchersAnnotatedElementFieldMatcherMirror p, String fieldName) { + Element e, ProvidesMatchersAnnotatedElementMatcherMirror p, String fieldName) { return removeIfNeededAndThenReturn( ((e instanceof ExecutableElement) ? ((ExecutableElement) e).getReturnType() : e.asType()) .accept(extractNameVisitor, false).map(f -> FieldDescriptionProvider.of(() -> p, @@ -108,7 +106,7 @@ public Optional createFieldDescriptionIfApplicableAndR @Override protected Optional defaultAction(Element e, - ProvidesMatchersAnnotatedElementFieldMatcherMirror p) { + ProvidesMatchersAnnotatedElementMatcherMirror p) { return Optional.empty(); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/RoundMirror.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/RoundMirror.java index a2bdd9701..0a1f90847 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/RoundMirror.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/RoundMirror.java @@ -157,7 +157,8 @@ private Matchable lookupMatchableByTypeAndMatchers(TypeElement type, TypeElement String withSameValue = shortMethodClassName + "WithSameValue"; boolean hasSameValue = methodsIn(guestMatcherEnclosed).stream().filter(t -> isSimpleName(t, withSameValue)) .anyMatch(this::isStatic); - return Matchable.of(getQualifiedName(guestMatcher), shortMethodClassName, guestMatcherName, hasSameValue); + return Matchable.of(getQualifiedName(guestMatcher), shortMethodClassName, guestMatcherName, hasSameValue, + compatibilityField.get()); } public AnnotationMirror getProvideMatchersAnnotation(Element e) { diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/extension/jackson/AbstractJacksonAutomatedExtension.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/extension/jackson/AbstractJacksonAutomatedExtension.java index ef15cb6c9..299053105 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/extension/jackson/AbstractJacksonAutomatedExtension.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/extension/jackson/AbstractJacksonAutomatedExtension.java @@ -70,7 +70,7 @@ public final Collection accept(AbstractFieldDescription field) { .filter(f -> f instanceof DefaultFieldDescription).map(DefaultFieldDescription.class::cast) .filter(f -> isAssignableWithErasure(f.getMirror().getFieldTypeAsTypeElement(), getTargetElement().asType())) - .map(this::acceptJsonMatcher).orElse(Collections.emptyList()); + .map(this::acceptJsonMatcher).orElseGet(Collections::emptyList); } /* diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/CollectionFieldDescription.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/CollectionFieldDescription.java index 89510d800..af3e2f764 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/CollectionFieldDescription.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/CollectionFieldDescription.java @@ -85,24 +85,24 @@ public List getDslForIterableWithGeneric() { } @Override - public String getFieldCopy(String lhs, String rhs) { + public String getFieldCopy(String lhs, String rhs, String ignore) { if (!"".equals(generic)) { return getFieldCopyForList(lhs, rhs); } - return super.getFieldCopy(lhs, rhs); + return super.getFieldCopy(lhs, rhs, ignore); } - public String getFieldCopyForList(String lhs, String rhs) { + protected String getFieldCopyForList(String lhs, String rhs) { String fieldAccessor = getFieldAccessor(); String fieldName = getFieldName(); - return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS - + ".nullValue()); } else if (" + rhs + "." + fieldAccessor + ".isEmpty()) {" + lhs + "." + fieldName - + "IsEmptyIterable(); } else {" + lhs + "." + fieldName + "Contains(" + rhs + "." + fieldAccessor - + ".stream().map(" + generateMatcherBuilderReferenceFor(generic) - + ").collect(java.util.stream.Collectors.toList())); }"; + return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS + + ".nullValue());\n} else if (" + rhs + "." + fieldAccessor + ".isEmpty()) {\n " + lhs + "." + + fieldName + "IsEmptyIterable();\n} else {\n " + lhs + "." + fieldName + "Contains(" + rhs + "." + + fieldAccessor + ".stream().map(" + generateMatcherBuilderReferenceFor(generic) + + ").collect(java.util.stream.Collectors.toList()));\n}"; } - public String generateMatcherBuilderReferenceFor(String generic) { + protected String generateMatcherBuilderReferenceFor(String generic) { return ofNullable(getByName(generic)).filter(Matchable::hasWithSameValue).map(t -> t.getWithSameValue(true)) .orElse(MATCHERS + "::is"); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/FieldDescriptionMetaData.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/FieldDescriptionMetaData.java index a35246ae2..c7c605afc 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/FieldDescriptionMetaData.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/FieldDescriptionMetaData.java @@ -20,6 +20,7 @@ package ch.powerunit.extensions.matchers.provideprocessor.fields; import static ch.powerunit.extensions.matchers.common.CommonUtils.toJavaSyntax; +import static java.lang.String.format; import static java.util.stream.Collectors.joining; import javax.lang.model.element.Element; @@ -28,14 +29,13 @@ import ch.powerunit.extensions.matchers.provideprocessor.Matchable; import ch.powerunit.extensions.matchers.provideprocessor.ProvidesMatchersAnnotatedElementData; +import ch.powerunit.extensions.matchers.provideprocessor.helper.FeatureMatcher; public abstract class FieldDescriptionMetaData extends AbstractFieldDescriptionContainerMetaData { public static final String SEE_TEXT_FOR_IS_MATCHER = "org.hamcrest.Matchers#is(java.lang.Object)"; public static final String SEE_TEXT_FOR_HAMCREST_MATCHER = "org.hamcrest.Matchers The main class from hamcrest that provides default matchers."; public static final String MATCHERS = "org.hamcrest.Matchers"; - public static final String MAIN_FIELD_COPY = "%1$s.%2$s(%3$s)"; - public static final String IS_MATCHER = "(org.hamcrest.Matcher)" + MATCHERS + ".is((java.lang.Object)%1$s.%2$s)"; protected final String generic; protected final String defaultReturnMethod; @@ -59,36 +59,26 @@ public FieldDescriptionMetaData(ProvidesMatchersAnnotatedElementData containingE } public String getMatcherForField() { - return String.format( - "private static class %1$sMatcher%2$s extends org.hamcrest.FeatureMatcher<%3$s%4$s,%5$s> {\n public %1$sMatcher(org.hamcrest.Matcher matcher) {\n super(matcher,\"%6$s\",\"%6$s\");\n }\n protected %5$s featureValueOf(%3$s%4$s actual) {\n return actual.%7$s;\n }\n}\n", - mirror.getMethodFieldName(), containingElementMirror.getFullGeneric(), + return new FeatureMatcher(mirror.getMethodFieldName(), containingElementMirror.getFullGeneric(), getFullyQualifiedNameEnclosingClassOfField(), containingElementMirror.getGeneric(), getFieldType(), - getFieldName(), getFieldAccessor()); + getFieldName(), "actual." + getFieldAccessor()).toString(); } - public String generateBaseFieldCopy(String lhs, String innerMatcher) { - return String.format(MAIN_FIELD_COPY, lhs, getFieldName(), innerMatcher); - } - - public String getFieldCopyDefault(String lhs, String rhs) { - return generateBaseFieldCopy(lhs, String.format(IS_MATCHER, rhs, getFieldAccessor())); - } - - public String getFieldCopySameRound(String lhs, String rhs, Matchable target) { - String fieldAccessor = getFieldAccessor(); - return generateBaseFieldCopy(lhs, rhs + "." + fieldAccessor + "==null?" + MATCHERS + ".nullValue():" - + target.getWithSameValue(false) + "(" + rhs + "." + fieldAccessor + ")"); - } - - public String getFieldCopy(String lhs, String rhs) { + public String getFieldCopy(String lhs, String rhs, String ignore) { return mirror.getMatchable(containingElementMirror.getRoundMirror()) .filter(a -> mirror.getFieldTypeAsTypeElement().getTypeParameters().isEmpty()) - .filter(Matchable::hasWithSameValue).map(p -> getFieldCopySameRound(lhs, rhs, p)) - .orElse(getFieldCopyDefault(lhs, rhs)); + .filter(Matchable::hasWithSameValue) + .map(p -> format( + "%1$s.%6$s(%2$s.%3$s == null ? org.hamcrest.Matchers.nullValue() : %4$s(%2$s.%3$s%5$s));", lhs, + rhs, getFieldAccessor(), p.getWithSameValue(false), p.supportIgnore() ? ignore : "", + getFieldName())) + .orElseGet(() -> format( + "%1$s.%4$s((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)%2$s.%3$s));", lhs, + rhs, getFieldAccessor(), getFieldName())); } public String asMatchesSafely() { - return String.format( + return format( "if(!%1$s.matches(actual)) {\n mismatchDescription.appendText(\"[\"); %1$s.describeMismatch(actual,mismatchDescription); mismatchDescription.appendText(\"]\\n\");\n result=false;\n}", getFieldName()); } @@ -98,8 +88,8 @@ public String asDescribeTo() { } public String asMatcherField() { - return String.format("private %1$sMatcher %2$s = new %1$sMatcher(%3$s.anything(%4$s));", - mirror.getMethodFieldName(), getFieldName(), MATCHERS, ""); + return format("private %1$sMatcher %2$s = new %1$sMatcher(%3$s.anything(%4$s));", mirror.getMethodFieldName(), + getFieldName(), MATCHERS, ""); } public String getFullyQualifiedNameEnclosingClassOfField() { diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescription.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescription.java index ebbf7b5ef..6b89b345e 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescription.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescription.java @@ -19,9 +19,11 @@ */ package ch.powerunit.extensions.matchers.provideprocessor.fields; +import static java.lang.String.format; +import static java.util.Optional.ofNullable; + import java.util.Collection; import java.util.Collections; -import java.util.Optional; import ch.powerunit.extensions.matchers.IgnoreInMatcher; import ch.powerunit.extensions.matchers.common.CommonUtils; @@ -51,18 +53,18 @@ public String getDslInterface() { @Override public String asMatcherField() { - return String.format("private %1$sMatcher %2$s = new %1$sMatcher(%3$s.anything(%4$s));", + return format("private %1$sMatcher %2$s = new %1$sMatcher(%3$s.anything(%4$s));", getMirror().getMethodFieldName(), getFieldName(), MATCHERS, "\"This field is ignored \"+" + CommonUtils.toJavaSyntax(getDescriptionForIgnoreIfApplicable())); } @Override - public String getFieldCopy(String lhs, String rhs) { + public String getFieldCopy(String lhs, String rhs, String ignore) { return "/* ignored - " + getFieldName() + " */"; } public String getDescriptionForIgnoreIfApplicable() { - return Optional.ofNullable(getFieldElement().getAnnotation(IgnoreInMatcher.class)).map(i -> i.comments()) + return ofNullable(getFieldElement().getAnnotation(IgnoreInMatcher.class)).map(IgnoreInMatcher::comments) .orElse(""); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/MapFieldDescription.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/MapFieldDescription.java index f96a7f6f5..1a8424ff0 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/MapFieldDescription.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/MapFieldDescription.java @@ -54,7 +54,7 @@ protected Collection getSpecificFieldDslMethodFor() { .map(o -> Optional.ofNullable(getByName(o)).filter(Matchable::hasWithSameValue) .map(t -> t.getWithSameValue(false)).orElse(MATCHERS + ".is")) .toArray()) - .orElse(new String[] { MATCHERS + ".is", MATCHERS + ".is" }); + .orElseGet(()->new String[] { MATCHERS + ".is", MATCHERS + ".is" }); tmp.add(generateHasSameValue(fieldType, matchers[0].toString(), matchers[1].toString())); } @@ -73,28 +73,15 @@ private FieldDSLMethod generateHasSameValue(String fieldType, String keyMatcher, } @Override - public String getMatcherForField() { - String matcher = super.getMatcherForField(); - if (!"".equals(generic)) { - String localGeneric = generic.contains("?") ? "" : "<" + generic + ">"; - matcher += "\n" + String.format( - "private static class %1$sMatcherSameValue%2$s extends org.hamcrest.FeatureMatcher<%3$s,%4$s> {\n public %1$sMatcherSameValue(org.hamcrest.Matcher matcher) {\n super(matcher,\"%5$s\",\"%5$s\");\n }\n protected %4$s featureValueOf(%3$s actual) {\n return (java.util.Set)actual.entrySet();\n }\n}\n", - mirror.getMethodFieldName(), containingElementMirror.getFullGeneric(), getFieldType(), - "java.util.Set", " [entries of] "); - } - return matcher; - } - - @Override - public String getFieldCopy(String lhs, String rhs) { + public String getFieldCopy(String lhs, String rhs, String ignore) { if (!"".equals(generic)) { String fieldAccessor = getFieldAccessor(); String fieldName = getFieldName(); - return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS - + ".nullValue()); } else {" + lhs + "." + fieldName + "HasSameValues(" + rhs + "." + fieldAccessor - + ");}"; + return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS + + ".nullValue());\n} else {\n " + lhs + "." + fieldName + "HasSameValues(" + rhs + "." + + fieldAccessor + ");\n}"; } - return super.getFieldCopy(lhs, rhs); + return super.getFieldCopy(lhs, rhs, ignore); } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/OptionalFieldDescription.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/OptionalFieldDescription.java index b7dca5278..a0b97e2f9 100644 --- a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/OptionalFieldDescription.java +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/fields/OptionalFieldDescription.java @@ -79,25 +79,28 @@ private Collection getAbsentDSL() { } @Override - public String getFieldCopy(String lhs, String rhs) { + public String getFieldCopy(String lhs, String rhs, String ignore) { if (!"".equals(generic)) { - return getFieldCopyForList(lhs, rhs); + return getFieldCopyForOptional(lhs, rhs, ignore); } - return super.getFieldCopy(lhs, rhs); + return super.getFieldCopy(lhs, rhs, ignore); } - public String getFieldCopyForList(String lhs, String rhs) { + public String getFieldCopyForOptional(String lhs, String rhs, String paramForHasSameValue) { String fieldAccessor = getFieldAccessor(); String fieldName = getFieldName(); - return "if(" + rhs + "." + fieldAccessor + "==null) {" + lhs + "." + fieldName + "(" + MATCHERS - + ".nullValue()); } else if (!" + rhs + "." + fieldAccessor + ".isPresent()) {" + lhs + "." + fieldName - + "IsAbsent(); } else {" + lhs + "." + fieldName + "IsPresentAndIs(" - + generateMatcherBuilderReferenceFor(generic, rhs + "." + fieldAccessor + ".get()") + "); }"; + return "if(" + rhs + "." + fieldAccessor + "==null) {\n " + lhs + "." + fieldName + "(" + MATCHERS + + ".nullValue());\n} else if (!" + rhs + "." + fieldAccessor + ".isPresent()) {\n " + lhs + "." + + fieldName + "IsAbsent();\n} else {\n " + lhs + "." + fieldName + "IsPresentAndIs(" + + generateMatcherBuilderReferenceFor(generic, rhs + "." + fieldAccessor + ".get()", + paramForHasSameValue) + + ");\n}"; } - public String generateMatcherBuilderReferenceFor(String generic, String accessor) { - return ofNullable(getByName(generic)).filter(Matchable::hasWithSameValue) - .map(t -> t.getWithSameValue(false) + "(" + accessor + ")").orElse(MATCHERS + ".is(" + accessor + ")"); + public String generateMatcherBuilderReferenceFor(String generic, String accessor, String paramForHasSameValue) { + return ofNullable(getByName(generic)).filter(Matchable::hasWithSameValue).map( + t -> t.getWithSameValue(false) + "(" + accessor + (t.supportIgnore() ? paramForHasSameValue : "") + ")") + .orElse(MATCHERS + ".is(" + accessor + ")"); } } diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.java new file mode 100644 index 000000000..69c40448b --- /dev/null +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.java @@ -0,0 +1,43 @@ +/** + * Powerunit - A JDK1.8 test framework + * Copyright (C) 2014 Mathieu Boretti. + * + * This file is part of Powerunit + * + * Powerunit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Powerunit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Powerunit. If not, see . + */ +package ch.powerunit.extensions.matchers.provideprocessor.helper; + +import static java.lang.String.format; + +import ch.powerunit.extensions.matchers.common.RessourceLoaderHelper; + +public final class FeatureMatcher { + + private static final String MATCHER_FORMAT = RessourceLoaderHelper.loadRessource(FeatureMatcher.class, + "FeatureMatcher.txt"); + + private final String matcher; + + public FeatureMatcher(String prefix, String genericOnTargetMatcher, String matcherOverClass, + String genericOnMatcherOverClass, String targetObject, String matcherDescription, String accessor) { + matcher = format(MATCHER_FORMAT, prefix, genericOnTargetMatcher, matcherOverClass, genericOnMatcherOverClass, + targetObject, matcherDescription, accessor); + } + + public String toString() { + return matcher; + } + +} diff --git a/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/ProvidesMatchersWithSameValueHelper.java b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/ProvidesMatchersWithSameValueHelper.java new file mode 100644 index 000000000..54c6d3ef4 --- /dev/null +++ b/src/main/java/ch/powerunit/extensions/matchers/provideprocessor/helper/ProvidesMatchersWithSameValueHelper.java @@ -0,0 +1,121 @@ +package ch.powerunit.extensions.matchers.provideprocessor.helper; + +import static ch.powerunit.extensions.matchers.common.CommonUtils.addPrefix; +import static ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod.of; +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.tools.Diagnostic.Kind; + +import ch.powerunit.extensions.matchers.provideprocessor.ProvidesMatchersAnnotatedElementMirror; +import ch.powerunit.extensions.matchers.provideprocessor.dsl.DSLMethod; +import ch.powerunit.extensions.matchers.provideprocessor.fields.AbstractFieldDescription; + +public final class ProvidesMatchersWithSameValueHelper { + + private ProvidesMatchersWithSameValueHelper() { + } + + private static DSLMethod generateWithSameValueWithParentMatcherIgnore(ProvidesMatchersAnnotatedElementMirror target, + boolean hasSuper) { + String genericNoParent = target.getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent(); + String simpleNameGenericNoParent = target.getSimpleNameOfGeneratedImplementationMatcherWithGenericNoParent(); + String simpleNameGenericWithParent = target + .getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(); + String fullyQualified = target.getFullyQualifiedNameOfGeneratedClass(); + String withSameValueMethodName = target.getMethodNameDSLWithSameValue(); + String fullGeneric = target.getFullGeneric(); + String argumentForParentBuilder = hasSuper + ? (target.getParentMirror() + .map(p -> p.getWithSameValue(false) + "(other" + (p.supportIgnore() ? ",ignoredFields" : "") + + ")") + .orElse("org.hamcrest.Matchers.anything()")) + : ""; + String javadoc = target.generateDefaultJavaDocWithoutDSLStarter(Optional.of( + "other the other object to be used as a reference.\n ignoredFields fields name that must be ignored."), + "the DSL matcher", false); + List lines = new ArrayList<>(); + lines.add("java.util.Set ignored = new java.util.HashSet<>(java.util.Arrays.asList(ignoredFields));"); + lines.add(genericNoParent + " m=new " + simpleNameGenericNoParent + "(" + argumentForParentBuilder + ");"); + target.getFields().stream().flatMap(ProvidesMatchersWithSameValueHelper::copyField).forEach(lines::add); + lines.add("return m;"); + return of(format("%1$s %2$s.%3$s %4$s", fullGeneric, fullyQualified, genericNoParent, withSameValueMethodName)) + .withArguments( + new String[][] { { simpleNameGenericWithParent, "other" }, { "String...", "ignoredFields" } }) + .withImplementation(lines).withJavadoc(javadoc); + } + + private static Stream copyField(AbstractFieldDescription f) { + return stream(format( + "if(!ignored.contains(\"%1$s\")) {\n String localIgnored[] = ignored.stream().filter(s->s.startsWith(\"%1$s.\")).map(s->s.replaceFirst(\"%1$s\\\\.\",\"\")).toArray(String[]::new);\n%2$s\n}", + f.getFieldName(), addPrefix(" ", f.getFieldCopy("m", "other", ",localIgnored"))).split("\n")); + } + + private static DSLMethod generateWithSameValueWithParentMatcherAndNoIgnore( + ProvidesMatchersAnnotatedElementMirror target) { + String withSameValueMethodName = target.getMethodNameDSLWithSameValue(); + return of(format("%1$s %2$s.%3$s %4$s", target.getFullGeneric(), target.getFullyQualifiedNameOfGeneratedClass(), + target.getSimpleNameOfGeneratedInterfaceMatcherWithGenericNoParent(), withSameValueMethodName)) + .withOneArgument(target.getFullyQualifiedNameOfClassAnnotatedWithProvideMatcherWithGeneric(), + "other") + .withImplementation(format("return %1$s(other,new String[]{});", withSameValueMethodName)) + .withJavadoc(target.generateDefaultJavaDocWithoutDSLStarter( + Optional.of("other the other object to be used as a reference."), "the DSL matcher", + false)); + } + + private static boolean isWeakAllowed(ProvidesMatchersAnnotatedElementMirror target) { + return target.getRealAnnotation().allowWeakWithSameValue(); + } + + private static void logWeak(ProvidesMatchersAnnotatedElementMirror target) { + Optional am = target.getAnnotationMirror(); + Optional av = am.map(a -> a.getElementValues().entrySet().stream() + .filter(kv -> kv.getKey().getSimpleName().toString().equals("allowWeakWithSameValue")) + .map(Entry::getValue).findAny().orElse(null)); + target.getMessager().printMessage(Kind.MANDATORY_WARNING, + "This class use the option allowWeakWithSameValue and a weak WithSameValue is detected. The generated WithSameValue DSL may not be able to fully control all the field of this class", + target.getElement(), am.orElse(null), av.orElse(null)); + } + + public static Collection> generateParentValueDSLStarter( + ProvidesMatchersAnnotatedElementMirror target) { + return asList(() -> target.getParentMirror() + .map(parentMirror -> generateWithSameValueWithParentMatcherIgnore(target, true)).orElseGet(() -> { + if (isWeakAllowed(target)) { + logWeak(target); + return generateWithSameValueWithParentMatcherIgnore(target, true); + } else { + return null; + } + }), + () -> target.getParentMirror() + .map(parentMirror -> generateWithSameValueWithParentMatcherAndNoIgnore(target)) + .orElseGet(() -> { + if (isWeakAllowed(target)) { + logWeak(target); + return generateWithSameValueWithParentMatcherAndNoIgnore(target); + } else { + return null; + } + })); + } + + public static Collection> generateNoParentValueDSLStarter( + ProvidesMatchersAnnotatedElementMirror target) { + return asList(() -> generateWithSameValueWithParentMatcherIgnore(target, false), + () -> generateWithSameValueWithParentMatcherAndNoIgnore(target)); + } + +} diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/Matchers.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/Matchers.txt new file mode 100644 index 000000000..a96464909 --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/Matchers.txt @@ -0,0 +1,45 @@ +package %1$s; + +/** + * This class provides matchers for the class {@link %2$s}. + * + * @see %2$s The class for which matchers are provided. + */ +%3$s +public final class %4$s { + + private %4$s() {} + + // + // --------------------------------------------------------------------------- + // Matchers for each fields + +%5$s + + // + // --------------------------------------------------------------------------- + // Public interface (Builder) for the matchers + +%6$s + + // + // --------------------------------------------------------------------------- + // Builder implementation + + +%7$s + + // + // --------------------------------------------------------------------------- + // DSL methods to start a matcher + + +%8$s + + // + // --------------------------------------------------------------------------- + // METADATA + +%9$s + +} \ No newline at end of file diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationNoParent.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationNoParent.txt new file mode 100644 index 000000000..07e93f324 --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationNoParent.txt @@ -0,0 +1,64 @@ +/* package protected */ static class %1$s%2$s + extends org.hamcrest.TypeSafeDiagnosingMatcher<%3$s> + implements %4$s { + + private final _PARENT _parentBuilder; + + private final java.util.List nextMatchers = new java.util.ArrayList<>(); + +%6$s + + public %1$s(_PARENT parentBuilder) { + this._parentBuilder=parentBuilder; + } + + public %1$s() { + this._parentBuilder=null; + } + +%7$s + + @Override + protected boolean matchesSafely(%5$s actual, + org.hamcrest.Description mismatchDescription) { + boolean result=true; + +%8$s + + for(org.hamcrest.Matcher nMatcher : nextMatchers) { + if(!nMatcher.matches(actual)) { + mismatchDescription.appendText("[object itself "); + nMatcher.describeMismatch(actual,mismatchDescription); + mismatchDescription.appendText("]\n"); + result=false; + } + } + + return result; + + } + + @Override + public void describeTo(org.hamcrest.Description description) { + description.appendText("an instance of %5$s with\n"); + +%9$s + + for(org.hamcrest.Matcher nMatcher : nextMatchers) { + description.appendText("[object itself ").appendDescriptionOf(nMatcher).appendText("]\n"); + } + + } + + @Override + public _PARENT end() { + return _parentBuilder; + } + + @Override + public %4$s andWith(org.hamcrest.Matcher otherMatcher) { + nextMatchers.add(java.util.Objects.requireNonNull(otherMatcher,"A matcher is expected")); + return this; + } + +} diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationParent.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationParent.txt new file mode 100644 index 000000000..6eb4ba380 --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersImplementationParent.txt @@ -0,0 +1,80 @@ +/* package protected */ static class %1$s%2$s + extends org.hamcrest.TypeSafeDiagnosingMatcher<%3$s> + implements %4$s { + + private final _PARENT _parentBuilder; + + private final java.util.List nextMatchers = new java.util.ArrayList<>(); + + private SuperClassMatcher _parent; + +%6$s + + public %1$s( + org.hamcrest.Matcher parent, + _PARENT parentBuilder) { + this._parent=new SuperClassMatcher(parent); + this._parentBuilder=parentBuilder; + } + + public %1$s(org.hamcrest.Matcher parent) { + this._parent=new SuperClassMatcher(parent); + this._parentBuilder=null; + } + +%7$s + + @Override + protected boolean matchesSafely(%5$s actual, + org.hamcrest.Description mismatchDescription) { + boolean result=true; + + if(!_parent.matches(actual)) { + mismatchDescription.appendText("["); + _parent.describeMismatch(actual,mismatchDescription); + mismatchDescription.appendText("]\n"); + + result=false; + } + +%8$s + + for(org.hamcrest.Matcher nMatcher : nextMatchers) { + if(!nMatcher.matches(actual)) { + mismatchDescription.appendText("[object itself "); + nMatcher.describeMismatch(actual,mismatchDescription); + mismatchDescription.appendText("]\n"); + result=false; + } + } + + return result; + + } + + @Override + public void describeTo(org.hamcrest.Description description) { + description.appendText("an instance of %5$s with\n"); + + description.appendText("[").appendDescriptionOf(_parent).appendText("]\n"); + +%9$s + + for(org.hamcrest.Matcher nMatcher : nextMatchers) { + description.appendText("[object itself ").appendDescriptionOf(nMatcher).appendText("]\n"); + } + + } + + @Override + public _PARENT end() { + return _parentBuilder; + } + + @Override + public %4$s andWith(org.hamcrest.Matcher otherMatcher) { + nextMatchers.add(java.util.Objects.requireNonNull(otherMatcher,"A matcher is expected")); + return this; + } + +} diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersInterface.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersInterface.txt new file mode 100644 index 000000000..4622261bc --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersInterface.txt @@ -0,0 +1,105 @@ +/** + * DSL interface for matcher on {@link %1$s %2$s} to support the build syntaxic sugar. + * +%3$s + * + */ +public static interface %4$sBuildSyntaxicSugar%5$s + extends org.hamcrest.Matcher<%6$s> { + + /** + * Method that returns the matcher itself. + *

+ * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore. + * + * @return the matcher + */ + default org.hamcrest.Matcher<%6$s> build() { + return this; + } + +} + +/** + * DSL interface for matcher on {@link %1$s %2$s} to support the end build syntaxic sugar. + * +%3$s + * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used to indicate no parent builder. + * + */ +public static interface %4$sEndSyntaxicSugar%7$s + extends org.hamcrest.Matcher<%6$s> { + + /** + * Method that returns the parent builder. + *

+ * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned. + * + * @return the parent builder or null if not applicable + */ + _PARENT end(); + +} + + +/** + * Start a DSL matcher for the {@link %1$s %2$s}. + * +%3$s + * + */ +public static interface %4$s%7$s + extends org.hamcrest.Matcher<%6$s>, + %4$sBuildSyntaxicSugar%8$s, + %4$sEndSyntaxicSugar%9$s { + +%10$s + + /** + * Add a matcher on the object itself and not on a specific field. + *

+ * This method, when used more than once, just add more matcher to the list. + * + * @param otherMatcher the matcher on the object itself. + * @return the DSL to continue + */ + %4$s%9$s andWith(org.hamcrest.Matcher otherMatcher); + + /** + * Add a matcher on the object itself and not on a specific field, but convert the object before passing it to the matcher. + *

+ * This method, when used more than once, just add more matcher to the list. + * + * @param converter the function to convert the object. + * @param otherMatcher the matcher on the converter object itself. + * @param <_TARGETOBJECT> the type of the target object + * @return the DSL to continue + */ + default <_TARGETOBJECT> %4$s%9$s andWithAs(java.util.function.Function<%6$s ,_TARGETOBJECT> converter,org.hamcrest.Matcher otherMatcher) { + return andWith(asFeatureMatcher(" ",converter,otherMatcher)); + } + + /** + * Method that return the matcher itself and accept one single Matcher on the object itself. + *

+ * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore. + * + * @param otherMatcher the matcher on the object itself. + * @return the matcher + */ + default org.hamcrest.Matcher<%6$s> buildWith(org.hamcrest.Matcher otherMatcher) { + return andWith(otherMatcher); + } + + /** + * Method that return the parent builder and accept one single Matcher on the object itself. + *

+ * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned. + * + * @param otherMatcher the matcher on the object itself. + * @return the parent builder or null if not applicable + */ + default _PARENT endWith(org.hamcrest.Matcher otherMatcher){ + return andWith(otherMatcher).end(); + } +} \ No newline at end of file diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersMetadata.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersMetadata.txt new file mode 100644 index 000000000..ba93bef5c --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/MatchersMetadata.txt @@ -0,0 +1,39 @@ + + /** + * Metadata regarding this matcher. + */ + public static final Metadata METADATA = new Metadata(); + + public static final class FieldMetadata { + public final String NAME, TYPE, ACCESSOR, STEREOTYPE; + + public final boolean IGNORED; + + private FieldMetadata(String name, String type, String accessor,String stereotype, boolean ignored) { + NAME=name; + TYPE=type; + ACCESSOR=accessor; + STEREOTYPE=stereotype; + IGNORED=ignored; + } + } + + + public static final class Metadata { + private Metadata() {} + + public final String ANNOTATION_PROCESSOR_VERSION = "%1$s"; + + public final long COMPATIBILITY = %2$sL; + + public final String SOURCE_CLASS_NAME = "%3$s"; + + public final Class<%4$s> SOURCE_CLASS = %4$s.class; + + public final String SOURCE_PARENT_CLASS_NAME = %5$s; + + public final FieldMetadata[] FIELDS = new FieldMetadata[]{ + %6$s + }; + + } diff --git a/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.txt b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.txt new file mode 100644 index 000000000..70a24ddab --- /dev/null +++ b/src/main/resources/ch/powerunit/extensions/matchers/provideprocessor/helper/FeatureMatcher.txt @@ -0,0 +1,9 @@ +private static class %1$sMatcher%2$s extends org.hamcrest.FeatureMatcher<%3$s%4$s,%5$s> { + public %1$sMatcher(org.hamcrest.Matcher matcher) { + super(matcher,"%6$s","%6$s"); + } + + protected %5$s featureValueOf(%3$s%4$s actual) { + return %7$s; + } +} \ No newline at end of file diff --git a/src/site/apt/link.apt b/src/site/apt/link.apt index 91757bc58..24302fdea 100644 --- a/src/site/apt/link.apt +++ b/src/site/apt/link.apt @@ -1,5 +1,7 @@ Detection of Matcher for Class +* General concepts + Conceptually, for every fields or parent classes, the annotation processor will try to find a Matcher to compare the values. This is done by detecting the relation @@ -20,7 +22,7 @@ Detection of Matcher for Class [] - Now, we have a second maven project, which uses the first one as dependency, with have the following annotated classes : + Now, we have a second maven project, which uses the first one as dependency, we have the following annotated classes : * <<>> which extends <<>> @@ -48,3 +50,33 @@ Detection of Matcher for Class * The method <<>> start a DSL to compare for same value. The <<>> from <<>> will be used for the control of <<>>. + + + [] + + [] + +* Limitations + +** Circular references + + It is possible to create classes that may produce <<>> for the <<>> matcher. This is the case with bidirectional class references or + as a more generic case, circular references. It is almost impossible to detect these case at compile time ; For example, event if a class <<>> has a field of class + <<>> and class <<>> a field of class <<>>, it is not possible to assume we have a bidirectional referencing (the issue is only when an instance of <<>> + references a specific instance of <<>> and this instance of <<>> references the previous instance of <<>>. + +*** Handling this case with version 0.2.0 + + In version 0.2.0, there are two different ways to manage these link : + + * At compile time, based on the structure on the link, it is possible to annotated one of the referencing fields with <<<@IgnoreInMatcher>>>. The field will be + ignored which will break the circular reference. + * At runtime time, modify manually (using the DSL), the returned matcher, to break the cycle. + +*** Handling this case with version latter 0.3.0 + + Since version 0.3.0, an additional <<>> methods is available to specify fields (based on field name) to be ignored. The two previous options are still + available, but it is also possible to use this ignore parameter. It is possible to chain the ignore by using a syntax like <<>>. + + \ No newline at end of file diff --git a/src/test/java/ch/powerunit/extensions/matchers/TestSuiteSupport.java b/src/test/java/ch/powerunit/extensions/matchers/TestSuiteSupport.java index 544614987..06c805ed6 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/TestSuiteSupport.java +++ b/src/test/java/ch/powerunit/extensions/matchers/TestSuiteSupport.java @@ -60,12 +60,13 @@ default ProcessingEnvironment generateMockitoProcessingEnvironment() { when(fullObjectName.toString()).thenReturn("ch.powerunit.extensions.matchers.ProvideMatchers"); Elements elements = mock(Elements.class); ProcessingEnvironment processingEnv = mock(ProcessingEnvironment.class); + Types types = mock(Types.class); when(processingEnv.getMessager()).thenReturn(mock(Messager.class)); when(processingEnv.getElementUtils()).thenReturn(elements); when(processingEnv.getFiler()).thenReturn(mock(Filer.class)); when(processingEnv.getLocale()).thenReturn(Locale.getDefault()); when(processingEnv.getOptions()).thenReturn(mock(Map.class)); - when(processingEnv.getTypeUtils()).thenReturn(mock(Types.class)); + when(processingEnv.getTypeUtils()).thenReturn(types); when(processingEnv.getSourceVersion()).thenReturn(SourceVersion.RELEASE_8); when(elements.getTypeElement("java.lang.Object")).thenReturn(object); when(elements.getTypeElement("ch.powerunit.extensions.matchers.ProvideMatchers")).thenReturn(provide); diff --git a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitorTest.java b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitorTest.java index ddd32392f..464056ed3 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitorTest.java +++ b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/NameExtractorVisitorTest.java @@ -62,98 +62,28 @@ private void prepare() { @Test(fastFail = false) public void testVisitPrimitiveAsBoolean() { - Optional r1 = underTest.visitPrimitiveAsBoolean(primitiveType, false); + when(processingEnv.getTypeUtils().boxedClass(primitiveType)).thenReturn(typeElement); + when(primitiveType.toString()).thenReturn("boolean"); + when(typeElement.toString()).thenReturn("Boolean"); + + Optional r1 = underTest.visitPrimitive(primitiveType, false); assertThat(r1).isNotNull(); assertThat(r1.orElse("error")).is("Boolean"); - Optional r2 = underTest.visitPrimitiveAsBoolean(primitiveType, true); + Optional r2 = underTest.visitPrimitive(primitiveType, true); assertThat(r2).isNotNull(); assertThat(r2.orElse("error")).is("boolean"); } - @Test(fastFail = false) - public void testVisitPrimitiveAsByte() { - Optional r1 = underTest.visitPrimitiveAsByte(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Byte"); - - Optional r2 = underTest.visitPrimitiveAsByte(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("byte"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsShort() { - Optional r1 = underTest.visitPrimitiveAsShort(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Short"); - - Optional r2 = underTest.visitPrimitiveAsShort(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("short"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsInt() { - Optional r1 = underTest.visitPrimitiveAsInt(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Integer"); - - Optional r2 = underTest.visitPrimitiveAsInt(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("int"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsLong() { - Optional r1 = underTest.visitPrimitiveAsLong(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Long"); - - Optional r2 = underTest.visitPrimitiveAsLong(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("long"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsChar() { - Optional r1 = underTest.visitPrimitiveAsChar(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Character"); - - Optional r2 = underTest.visitPrimitiveAsChar(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("char"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsFloat() { - Optional r1 = underTest.visitPrimitiveAsFloat(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Float"); - - Optional r2 = underTest.visitPrimitiveAsFloat(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("float"); - } - - @Test(fastFail = false) - public void testVisitPrimitiveAsDouble() { - Optional r1 = underTest.visitPrimitiveAsDouble(primitiveType, false); - assertThat(r1).isNotNull(); - assertThat(r1.orElse("error")).is("Double"); - - Optional r2 = underTest.visitPrimitiveAsDouble(primitiveType, true); - assertThat(r2).isNotNull(); - assertThat(r2.orElse("error")).is("double"); - } - @Test(fastFail = false) public void testVisitArray() { + when(processingEnv.getTypeUtils().boxedClass(primitiveType)).thenReturn(typeElement); + when(primitiveType.toString()).thenReturn("boolean"); + when(typeElement.toString()).thenReturn("Boolean"); when(arrayType.getComponentType()).thenReturn(primitiveType); when(primitiveType.getKind()).thenReturn(TypeKind.BOOLEAN); when(primitiveType.accept(Mockito.any(), Mockito.any())) - .thenAnswer(ip -> ip.getArgumentAt(0, TypeKindVisitor8.class).visitPrimitiveAsBoolean(primitiveType, + .thenAnswer(ip -> ip.getArgumentAt(0, TypeKindVisitor8.class).visitPrimitive(primitiveType, ip.getArgumentAt(1, Object.class))); Optional r1 = underTest.visitArray(arrayType, false); diff --git a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirrorTest.java b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirrorTest.java index 980529f69..5f0501215 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirrorTest.java +++ b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/ProvidesMatchersAnnotatedElementMirrorTest.java @@ -97,7 +97,7 @@ public void testGeneratePublicInterfaceWithoutField() { ProvidesMatchersAnnotatedElementMirror underTest = new ProvidesMatchersAnnotatedElementMirror(typeElement, roundMirror); assertThat(underTest.generatePublicInterface()).is( - "\n /**\n * DSL interface for matcher on {@link fqn.Sn Sn} to support the build syntaxic sugar.\n * \n * \n */\n\n public static interface SnMatcherBuildSyntaxicSugar extends org.hamcrest.Matcher {\n\n /**\n * Method that return the matcher itself..\n *

\n * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore.\n * @return the matcher\n */\n\n default org.hamcrest.Matcher build() {\n return this;\n }\n }\n\n /**\n * DSL interface for matcher on {@link fqn.Sn Sn} to support the end syntaxic sugar.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n */\n\n public static interface SnMatcherEndSyntaxicSugar<_PARENT> extends org.hamcrest.Matcher {\n\n /**\n * Method that return the parent builder.\n *

\n * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned.\n * @return the parent builder or null if not applicable\n */\n\n _PARENT end();\n }\n\n /**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n * \n */\n\n public static interface SnMatcher<_PARENT> extends org.hamcrest.Matcher,SnMatcherBuildSyntaxicSugar ,SnMatcherEndSyntaxicSugar <_PARENT> {\n\n\n /**\n * Add a matcher on the object itself and not on a specific field.\n *

\n * This method, when used more than once, just add more matcher to the list.\n * @param otherMatcher the matcher on the object itself.\n * @return the DSL to continue\n */\n SnMatcher <_PARENT> andWith(org.hamcrest.Matcher otherMatcher);\n\n /**\n * Add a matcher on the object itself and not on a specific field, but convert the object before passing it to the matcher.\n *

\n * This method, when used more than once, just add more matcher to the list.\n * @param converter the function to convert the object.\n * @param otherMatcher the matcher on the converter object itself.\n * @param <_TARGETOBJECT> the type of the target object\n * @return the DSL to continue\n */\n default <_TARGETOBJECT> SnMatcher <_PARENT> andWithAs(java.util.function.Function converter,org.hamcrest.Matcher otherMatcher) {\n return andWith(asFeatureMatcher(\" \",converter,otherMatcher));\n }\n\n\n /**\n * Method that return the matcher itself and accept one single Matcher on the object itself..\n *

\n * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore.\n * @param otherMatcher the matcher on the object itself.\n * @return the matcher\n */\n\n default org.hamcrest.Matcher buildWith(org.hamcrest.Matcher otherMatcher) {\n return andWith(otherMatcher);\n }\n\n\n /**\n * Method that return the parent builder and accept one single Matcher on the object itself..\n *

\n * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned.\n * @param otherMatcher the matcher on the object itself.\n * @return the parent builder or null if not applicable\n */\n default _PARENT endWith(org.hamcrest.Matcher otherMatcher){\n return andWith(otherMatcher).end();\n }\n }\n"); + "\n /**\n * DSL interface for matcher on {@link fqn.Sn Sn} to support the build syntaxic sugar.\n * \n * \n \n *\n */\n public static interface SnMatcherBuildSyntaxicSugar\n extends org.hamcrest.Matcher {\n \n /**\n * Method that returns the matcher itself.\n *

\n * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore.\n *\n * @return the matcher\n */\n default org.hamcrest.Matcher build() {\n return this;\n }\n \n }\n \n /**\n * DSL interface for matcher on {@link fqn.Sn Sn} to support the end build syntaxic sugar.\n * \n * \n \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used to indicate no parent builder.\n *\n */\n public static interface SnMatcherEndSyntaxicSugar<_PARENT>\n extends org.hamcrest.Matcher {\n \n /**\n * Method that returns the parent builder.\n *

\n * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned.\n *\n * @return the parent builder or null if not applicable\n */\n _PARENT end();\n \n }\n \n \n /**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * \n * \n \n *\n */\n public static interface SnMatcher<_PARENT>\n extends org.hamcrest.Matcher,\n SnMatcherBuildSyntaxicSugar,\n SnMatcherEndSyntaxicSugar<_PARENT> {\n \n \n \n /**\n * Add a matcher on the object itself and not on a specific field.\n *

\n * This method, when used more than once, just add more matcher to the list.\n *\n * @param otherMatcher the matcher on the object itself.\n * @return the DSL to continue\n */\n SnMatcher<_PARENT> andWith(org.hamcrest.Matcher otherMatcher);\n \n /**\n * Add a matcher on the object itself and not on a specific field, but convert the object before passing it to the matcher.\n *

\n * This method, when used more than once, just add more matcher to the list.\n *\n * @param converter the function to convert the object.\n * @param otherMatcher the matcher on the converter object itself.\n * @param <_TARGETOBJECT> the type of the target object\n * @return the DSL to continue\n */\n default <_TARGETOBJECT> SnMatcher<_PARENT> andWithAs(java.util.function.Function converter,org.hamcrest.Matcher otherMatcher) {\n return andWith(asFeatureMatcher(\" \",converter,otherMatcher));\n }\n \n /**\n * Method that return the matcher itself and accept one single Matcher on the object itself.\n *

\n * This method is a syntaxic sugar that end the DSL and make clear that the matcher can't be change anymore.\n *\n * @param otherMatcher the matcher on the object itself.\n * @return the matcher\n */\n default org.hamcrest.Matcher buildWith(org.hamcrest.Matcher otherMatcher) {\n return andWith(otherMatcher);\n }\n \n /**\n * Method that return the parent builder and accept one single Matcher on the object itself.\n *

\n * This method only works in the context of a parent builder. If the real type is Void, then nothing will be returned.\n *\n * @param otherMatcher the matcher on the object itself.\n * @return the parent builder or null if not applicable\n */\n default _PARENT endWith(org.hamcrest.Matcher otherMatcher){\n return andWith(otherMatcher).end();\n }\n }\n"); } @Test @@ -105,9 +105,9 @@ public void testGenerateDSLStarter() { ProvidesMatchersAnnotatedElementMirror underTest = new ProvidesMatchersAnnotatedElementMirror(typeElement, roundMirror); Collection results = underTest.generateDSLStarter(); - assertThat(results).is(iterableWithSize(3)); + assertThat(results).is(iterableWithSize(4)); assertThat(results.stream().map(x -> x.asStaticImplementation()).collect(Collectors.joining("\n"))).is( - "/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n *

\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher snWith() {\n return new SnMatcherImpl();\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n *

\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * @param parentBuilder the parentBuilder.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n * @return the DSL matcher\n */\npublic static <_PARENT> fqn.SnMatchers.SnMatcher <_PARENT> snWithParent(_PARENT parentBuilder) {\n return new SnMatcherImpl<_PARENT>(parentBuilder);\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher snWithSameValue(fqn.Sn other) {\n SnMatcher m=new SnMatcherImpl();\n return m;\n}\n"); + "/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n *

\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher snWith() {\n return new SnMatcherImpl();\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n *

\n * The returned builder (which is also a Matcher), at this point accepts any object that is a {@link fqn.Sn Sn}.\n * @param parentBuilder the parentBuilder.\n * \n * \n * @param <_PARENT> used to reference, if necessary, a parent for this builder. By default Void is used an indicate no parent builder.\n * @return the DSL matcher\n */\npublic static <_PARENT> fqn.SnMatchers.SnMatcher <_PARENT> snWithParent(_PARENT parentBuilder) {\n return new SnMatcherImpl<_PARENT>(parentBuilder);\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * @param ignoredFields fields name that must be ignored.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher snWithSameValue(fqn.Sn other,String... ignoredFields) {\n java.util.Set ignored = new java.util.HashSet<>(java.util.Arrays.asList(ignoredFields));\n SnMatcher m=new SnMatcherImpl();\n return m;\n}\n\n/**\n * Start a DSL matcher for the {@link fqn.Sn Sn}.\n * @param other the other object to be used as a reference.\n * \n * \n * @return the DSL matcher\n */\npublic static fqn.SnMatchers.SnMatcher snWithSameValue(fqn.Sn other) {\n return snWithSameValue(other,new String[]{});\n}\n"); } } diff --git a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/dsl/DSLMethodTest.java b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/dsl/DSLMethodTest.java index 79390d9d1..31065979e 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/dsl/DSLMethodTest.java +++ b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/dsl/DSLMethodTest.java @@ -38,4 +38,23 @@ public void testDSLMethodTwoArgument() { assertThat(m.asDefaultReference("target")).is( "/**\n * l1\n * l2\n */\ndefault boolean isOK(java.lang.String one,java.lang.String two) {\n return target.isOK(one,two);\n}\n"); } + + @Test(fastFail = false) + public void testDSLMethodOneArgument() { + DSLMethod m = DSLMethod.of("boolean isOK").addOneArgument("java.lang.String", "one").withImplementation("l1") + .withJavadoc(new String[] { "l1", "l2" }); + assertThat(m.asStaticImplementation()) + .is("/**\n * l1\n * l2\n */\npublic static boolean isOK(java.lang.String one) {\n l1\n}\n"); + assertThat(m.asDefaultReference("target")).is( + "/**\n * l1\n * l2\n */\ndefault boolean isOK(java.lang.String one) {\n return target.isOK(one);\n}\n"); + } + + @Test(fastFail = false) + public void testDSLMethodZeroArgument() { + DSLMethod m = DSLMethod.of("boolean isOK").withoutArgument().withImplementation("l1") + .withJavadoc(new String[] { "l1", "l2" }); + assertThat(m.asStaticImplementation()).is("/**\n * l1\n * l2\n */\npublic static boolean isOK() {\n l1\n}\n"); + assertThat(m.asDefaultReference("target")) + .is("/**\n * l1\n * l2\n */\ndefault boolean isOK() {\n return target.isOK();\n}\n"); + } } diff --git a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/DefaultFieldDescriptionTest.java b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/DefaultFieldDescriptionTest.java index f77abc490..2251e4896 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/DefaultFieldDescriptionTest.java +++ b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/DefaultFieldDescriptionTest.java @@ -138,12 +138,12 @@ public void testAsMatchesSafely() { } @Test - public void testGetFieldCopy() { + public void testGetFieldCopyIgnore() { DefaultFieldDescription undertest = new DefaultFieldDescription(() -> provideMatchersAnnotatedElementMirror, new FieldDescriptionMirror(() -> provideMatchersAnnotatedElementMirror, "field", "boolean", executableElement)); - assertThat(undertest.getFieldCopy("a", "b")) - .is("a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()))"); + assertThat(undertest.getFieldCopy("a", "b", ",x")) + .is("a.field((org.hamcrest.Matcher)org.hamcrest.Matchers.is((java.lang.Object)b.field()));"); } @Test @@ -152,7 +152,7 @@ public void testGetMatcherForField() { new FieldDescriptionMirror(() -> provideMatchersAnnotatedElementMirror, "field", "boolean", executableElement)); assertThat(undertest.getMatcherForField()).is( - "private static class FieldMatcher extends org.hamcrest.FeatureMatcher {\n public FieldMatcher(org.hamcrest.Matcher matcher) {\n super(matcher,\"field\",\"field\");\n }\n protected boolean featureValueOf(fqn.sn actual) {\n return actual.field();\n }\n}\n"); + "private static class FieldMatcher extends org.hamcrest.FeatureMatcher {\n public FieldMatcher(org.hamcrest.Matcher matcher) {\n super(matcher,\"field\",\"field\");\n }\n\n protected boolean featureValueOf(fqn.sn actual) {\n return actual.field();\n }\n}\n"); } @Test diff --git a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescriptionTest.java b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescriptionTest.java index 67fb2a592..ce6a14795 100644 --- a/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescriptionTest.java +++ b/src/test/java/ch/powerunit/extensions/matchers/provideprocessor/fields/IgnoreFieldDescriptionTest.java @@ -100,7 +100,7 @@ public void testAsMatcherField() { @Test public void testGetFieldCopy() { - String result = new IgnoreFieldDescription(element, field).getFieldCopy("lhs", "rhs"); + String result = new IgnoreFieldDescription(element, field).getFieldCopy("lhs", "rhs",""); assertThat(result).is("/* ignored - fn */"); } diff --git a/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojo.java b/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojo.java deleted file mode 100644 index ae24a4f48..000000000 --- a/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojo.java +++ /dev/null @@ -1,12 +0,0 @@ -package ch.powerunit.extensions.matchers.samples.extensions.jackson; - -import com.fasterxml.jackson.databind.JsonNode; - -import ch.powerunit.extensions.matchers.ProvideMatchers; - -@ProvideMatchers(extensions = ProvideMatchers.JSON_EXTENSION) -public class JacksonPojo { - - public JsonNode p1; - -} diff --git a/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojoDisabled.java b/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojoDisabled.java deleted file mode 100644 index 00458dff1..000000000 --- a/src/test/java/ch/powerunit/extensions/matchers/samples/extensions/jackson/JacksonPojoDisabled.java +++ /dev/null @@ -1,12 +0,0 @@ -package ch.powerunit.extensions.matchers.samples.extensions.jackson; - -import com.fasterxml.jackson.databind.JsonNode; - -import ch.powerunit.extensions.matchers.ProvideMatchers; - -@ProvideMatchers(extensions = {}) -public class JacksonPojoDisabled { - - public JsonNode p1; - -}