-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use imports instead of FQN #97 #99
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,9 +22,12 @@ | |
import java.io.File; | ||
import java.io.FileWriter; | ||
import java.io.IOException; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.SortedSet; | ||
import java.util.TreeSet; | ||
|
@@ -319,14 +322,54 @@ private String generateAssertionsEntryPointClassContent(final Set<ClassDescripti | |
? determineBestEntryPointsAssertionsClassPackage(classDescriptionSet) | ||
: entryPointClassPackage; | ||
entryPointAssertionsClassContent = replace(entryPointAssertionsClassContent, PACKAGE, classPackage); | ||
|
||
String imports = buildImports(classDescriptionSet); | ||
entryPointAssertionsClassContent = replace(entryPointAssertionsClassContent, IMPORTS, imports); | ||
String allEntryPointsAssertionContent = generateAssertionEntryPointMethodsFor(classDescriptionSet, | ||
entryPointAssertionMethodTemplate); | ||
entryPointAssertionsClassContent = replace(entryPointAssertionsClassContent, ALL_ASSERTIONS_ENTRY_POINTS, | ||
allEntryPointsAssertionContent); | ||
return entryPointAssertionsClassContent; | ||
} | ||
|
||
private static String buildImports(Set<ClassDescription> classDescriptionSet) { | ||
StringBuilder builder = new StringBuilder(); | ||
for (String anImport : extractImports(classDescriptionSet)) { | ||
builder.append(format(IMPORT_LINE, anImport, LINE_SEPARATOR)); | ||
} | ||
return builder.toString(); | ||
} | ||
|
||
/** | ||
* The set will contain all the FQN of the imports for which simple class names can be used. | ||
* <p> | ||
* Example: | ||
* <pre> | ||
* org.example.Outer -> part of the set | ||
* org.example.Outer.Inner -> org.example.Outer in the result | ||
* org.example.other.Outer -> not in the set because another FQN for the same simple class name Outer already exists | ||
* org.example.other.Outer.Inner -> same as above, another FQN for the same outer class name exists | ||
* </pre> | ||
* | ||
* @param classDescriptionSet for which we need to extract the imports | ||
* @return a sorted set with all the FQN that can be imported | ||
*/ | ||
private static SortedSet<String> extractImports(Set<ClassDescription> classDescriptionSet) { | ||
Map<String, String> importedQualifiedName = new HashMap<>(classDescriptionSet.size() * 2); | ||
for (final ClassDescription description : new TreeSet<>(classDescriptionSet)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to create a new There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not necessarily, do we want to have some ordering of the imports, i.e. Do we want to first methods to always have a normal import and then the methods below to use FQN in case that is needed? What we can do is to pass a |
||
final String outerClassName = description.getOuterClassName(); | ||
if (!importedQualifiedName.containsKey(outerClassName)) { | ||
String toImport = description.getPackageName() + "." + outerClassName; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
importedQualifiedName.put(outerClassName, toImport); | ||
} | ||
|
||
if (!importedQualifiedName.containsKey(simpleAssertClassName(description))) { | ||
String toImport = fullyQualifiedAssertClassName(description); | ||
importedQualifiedName.put(simpleAssertClassName(description), toImport); | ||
} | ||
} | ||
return new TreeSet<>(importedQualifiedName.values()); | ||
} | ||
|
||
/** | ||
* create the assertions entry point file, located in its package directory starting from targetBaseDirectory. | ||
* <p> | ||
|
@@ -353,6 +396,7 @@ private File createAssertionsFileFor(final Set<ClassDescription> classDescriptio | |
|
||
private String generateAssertionEntryPointMethodsFor(final Set<ClassDescription> classDescriptionSet, | ||
Template assertionEntryPointMethodTemplate) { | ||
SortedSet<String> resolvedImports = extractImports(classDescriptionSet); | ||
// sort ClassDescription according to their class name. | ||
SortedSet<ClassDescription> sortedClassDescriptionSet = new TreeSet<ClassDescription>(classDescriptionSet); | ||
// generate for each classDescription the entry point method, e.g. assertThat(MyClass) or then(MyClass) | ||
|
@@ -362,12 +406,23 @@ private String generateAssertionEntryPointMethodsFor(final Set<ClassDescription> | |
String assertionEntryPointMethodContent = assertionEntryPointMethodTemplate.getContent(); | ||
// resolve class assert (ex: PlayerAssert) | ||
// in case of inner classes like Movie.PublicCategory, class assert will be MoviePublicCategoryAssert | ||
String customAssertionClass = fullyQualifiedAssertClassName(classDescription); | ||
if (resolvedImports.contains(customAssertionClass)) { | ||
// if the FQN exists in the resolved imports then we can use its simple class name instead | ||
customAssertionClass = simpleAssertClassName(classDescription); | ||
} | ||
assertionEntryPointMethodContent = replace(assertionEntryPointMethodContent, CUSTOM_ASSERTION_CLASS, | ||
fullyQualifiedAssertClassName(classDescription)); | ||
customAssertionClass); | ||
// resolve class (ex: Player) | ||
// in case of inner classes like Movie.PublicCategory use class name with outer class i.e. Movie.PublicCategory. | ||
String classToAssert = classDescription.getFullyQualifiedClassName(); | ||
if (resolvedImports.contains(classDescription.getPackageName() + "." + classDescription.getOuterClassName())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use the |
||
// if the FQN exists in the resolved imports then we can use its simple class name instead or the | ||
// simple class name of its outer class like in the case of Movie.PublicCategory | ||
classToAssert = classDescription.getClassNameWithOuterClass(); | ||
} | ||
assertionEntryPointMethodContent = replace(assertionEntryPointMethodContent, CLASS_TO_ASSERT, | ||
classDescription.getFullyQualifiedClassName()); | ||
classToAssert); | ||
allAssertThatsContentBuilder.append(lineSeparator).append(assertionEntryPointMethodContent); | ||
} | ||
return allAssertThatsContentBuilder.toString(); | ||
|
@@ -405,7 +460,11 @@ private static String abstractAssertClassNameOf(TypeName type) { | |
} | ||
|
||
private static String fullyQualifiedAssertClassName(ClassDescription classDescription) { | ||
return classDescription.getPackageName() + "." + classDescription.getClassNameWithOuterClassNotSeparatedByDots() | ||
return classDescription.getPackageName() + "." + simpleAssertClassName(classDescription); | ||
} | ||
|
||
private static String simpleAssertClassName(ClassDescription classDescription) { | ||
return classDescription.getClassNameWithOuterClassNotSeparatedByDots() | ||
+ ASSERT_CLASS_SUFFIX; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -475,6 +475,30 @@ public static String getSimpleNameWithOuterClass(Class<?> clazz) { | |
return nestedClassName; | ||
} | ||
|
||
/** | ||
* Gets the simple name of the outer class, if the class is not nested then this is the same as | ||
* {@link Class#getSimpleName()}. | ||
* <p> | ||
* Example: | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an example would be welcome |
||
* <pre> | ||
* OnlyOuter -> OnlyOuter | ||
* Outer.Inner -> Outer | ||
* Outer.Inner1.Inner2 -> Outer | ||
* </pre> | ||
* @param clazz for which the outer class name should be found | ||
* @return see description | ||
*/ | ||
public static String getSimpleNameOuterClass(Class<?> clazz) { | ||
if (isNotNestedClass(clazz)) { | ||
return clazz.getSimpleName(); | ||
} | ||
String outerClassName = clazz.getName(); | ||
outerClassName = outerClassName.substring(clazz.getPackage().getName().length() + 1); | ||
outerClassName = outerClassName.substring(0, outerClassName.indexOf('$')); | ||
return outerClassName; | ||
} | ||
|
||
/** | ||
* Gets the simple name of the class but, unlike {@link Class#getSimpleName()}, it includes the name of the outer | ||
* class when <code>clazz</code> is an inner class, both class names are concatenated. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package ${package}; | ||
|
||
${imports} | ||
/** | ||
* Entry point for BDD assertions of different data types. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package ${package}; | ||
|
||
${imports} | ||
/** | ||
* Entry point for BDD soft assertions of different data types. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package ${package}; | ||
|
||
${imports} | ||
/** | ||
* Entry point for soft assertions of different data types. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
import static org.assertj.assertions.generator.util.ClassUtil.getClassesRelatedTo; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getNegativePredicateFor; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getPredicatePrefix; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameOuterClass; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClass; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getSimpleNameWithOuterClassNotSeparatedByDots; | ||
import static org.assertj.assertions.generator.util.ClassUtil.getterMethodsOf; | ||
|
@@ -211,6 +212,13 @@ public void should_return_inner_class_name_with_outer_class_name(NestedClass nes | |
assertThat(actualName).isEqualTo(nestedClass.getClassNameWithOuterClass()); | ||
} | ||
|
||
@Theory | ||
public void should_return_outer_class_name_for_nested_class(NestedClass nestedClass) { | ||
String actualName = getSimpleNameOuterClass(nestedClass.getNestedClass()); | ||
assertThat(actualName).isEqualTo(nestedClass.getOuterClassName()); | ||
} | ||
|
||
|
||
@Theory | ||
public void should_return_inner_class_name_with_outer_class_name_not_separated_by_dots(NestedClass nestedClass) { | ||
String actualName = getSimpleNameWithOuterClassNotSeparatedByDots(nestedClass.getNestedClass()); | ||
|
@@ -228,6 +236,11 @@ public void testGetSimpleNameWithOuterClass_notNestedClass() throws Exception { | |
assertThat(ClassUtil.getSimpleNameWithOuterClass(String.class)).isEqualTo("String"); | ||
} | ||
|
||
@Test | ||
public void testGetSimpleNameOuterClass_notNestedClass() throws Exception { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rename the test using an english sentence to express what the test verifies then put Note: starting test method is redundant since we already have an |
||
assertThat(ClassUtil.getSimpleNameOuterClass(String.class)).isEqualTo("String"); | ||
} | ||
|
||
@Test | ||
public void getClass_on_parameterized_List_should_return_List_class() throws Exception { | ||
Method method = Generic.class.getMethod("getListOfInteger"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
importByClassName
would be more expressive thanimportedQualifiedName