-
Notifications
You must be signed in to change notification settings - Fork 39
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
Introduce validator for Refaster template collections and tests #43
Introduce validator for Refaster template collections and tests #43
Conversation
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.
Some context 😄.
* | ||
* @return A mapping from Refaster template names to {@link CodeTransformer}s. | ||
*/ | ||
public static ImmutableListMultimap<String, CodeTransformer> loadAllCodeTransformers() { |
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.
These methods are all coming from the RefasterCheck
(link). These methods are almost exactly the same (see one change I'll point out in getClassPathResources()
).
|
||
private static ImmutableSet<ResourceInfo> getClassPathResources() { | ||
try { | ||
return ClassPath.from(ClassLoader.getSystemClassLoader()).getResources(); |
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.
Here we changed from RefasterCheck.class.getClassLoader()
to the backup (link).
In the "old' situation we needed to get the resources (the *TemplatesTest{Input,Output}.java
files) from the same module as RefasterCheck
was in. Now that this is in a new module, we need the SystemClassLoader
.
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.
See #121: this change actually completely breaks the check (the tests just don't show that).
@@ -178,57 +169,4 @@ private static CodeTransformer createCompositeCodeTransformer(ErrorProneFlags fl | |||
.map(Map.Entry::getValue) | |||
.collect(toImmutableList()); | |||
} | |||
|
|||
private static ImmutableListMultimap<String, CodeTransformer> loadAllCodeTransformers() { |
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.
So these methods moved to CodeTransformers.java
* | ||
* @param clazz The Refaster template collection under test. | ||
*/ | ||
public static void validateTemplateCollection(Class<?> clazz) { |
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.
For this method we are limited to what the API of BugCheckerRefactoringTestHelper
offers us. We want to open a PR upstream to make this method public
instead of private
. In that case, we can improve this method because we can just pass the input and output file without retrieving the content first (which, for now, is an OK solution).
name = "RefasterTestBugChecker", | ||
summary = "Validate a Refaster template collection and its tests", | ||
severity = ERROR) | ||
public static final class RefasterTestBugChecker extends BugChecker |
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.
This is the check where the magic happens.
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.
Super great to see this, can only imagine that you're pretty proud of this. In the middle of reviewing, only where "the magic happens" to go. Got a few questions and suggestions already.
@@ -0,0 +1,4 @@ | |||
/** Utilities that support testing Refaster templates and validate the tests. */ |
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.
IIUC, the latter is based on the former. I'd make this more explicit by stronger coupling. Also, the sentence reads a bit weirdly because the former has a gerund (if I know my grammar) while the latter has not. Suggesting:
/** Utilities that support testing Refaster templates and validate the tests. */ | |
/** Utilities that support testing Refaster templates and allows for validating these tests. */ |
|
||
@VisibleForTesting | ||
static final Supplier<ImmutableListMultimap<String, CodeTransformer>> ALL_CODE_TRANSFORMERS = |
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.
This can be private now (if you don't keep the tests). Or you can move it to CodeTransformers
and keep it package private; this might be cleaner from a test-perspective (for the loadAllCodeTransformers
test).
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.
Good catch.
Or you can move it to CodeTransformers and keep it package private;
It is also used in the refaster-test-support
so making it package-private is currently not an option.
Also considered moving the Supplier
as is into the CodeTransformers
class. Not sure if it would be improvement currently. Not a good idea or opinion about what would be the best approach for now.
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.
Also considered moving the
Supplier
as is into theCodeTransformers
class. Not sure if it would be improvement currently. Not a good idea or opinion about what would be the best approach for now.
IMHO we should do that, since now we load the classpath resources twice.
/** Classes used to find Refaster templates on the classpath and to apply them. */ | ||
@com.google.errorprone.annotations.CheckReturnValue | ||
@javax.annotation.ParametersAreNonnullByDefault | ||
package tech.picnic.errorprone.refaster.runner; |
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.
Currently, I don't see much value in the module refaster-runner
as it is only used by refaster-test-support
. Do you envision functionality where runners are not only used in test context but also in a different context? If not, I'd suggest consolidating the two modules because of YAGNI.
Main reason why I tripped over this, is because this module doesn't have any tests anymore. Which I get, because the RefasterCheck
and CodeTransformers
logic is covered by RefasterCollectionTestUtil
. But that class resides in a different module now. This link might become obscure once both modules keep growing causing it harder to debug test failures as a result of refaster-runner
changes in the future. We could also keep some minimal level of testing in refaster-runner
(see other comment).
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.
We specifically choose to split refaster-runner
and refaster-test-support
.
refaster-runner
andrefaster-test-support
are doing two completely different things. Therefaster-runner
runs during compilation and handles everything with regards to compiling the resources and the classpath. Thetest-support
contains things that we can use during thetest
phase (so only in the context of compiling & running tests) and help with validation of templates and tests. Sorefaster-test-support
can be used with<scope>test</scope>
, which is different fromrefaster-runner
.- We want people to be able to use & depend the
refaster-runner
without having to depend on / use things from therefaster-test-support
. - We created a setup (module-wise) that we want to work towards and this is part of that.
This module doesn't have any tests anymore.
We decided to defer this for now. The tests in RefasterCheckTest
are mostly based on the test resources from error-prone-contrib
and is not what we actually want to test in refaster-runner
. The replacement
method highlighted in the other comment is part of what we test with the validateTemplateCollection
(now we test more than previously).
So I agree that we should have more tests in refaster-runner
but as I said, we want to defer that for now 😄.
*/ | ||
@MethodSource("templateGroupsUnderTest") | ||
@ParameterizedTest | ||
void replacement(String group) { |
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 feel we can keep some of these tests (like this one), possibly isolate them a bit more, and place them under refaster-runner
. This would help in identifying erroneous changes to the classes in this package. We could create a few dummy templates to verify the RefasterCheck
and CodeTransformers
logic.
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.
See other comment :)
refaster-test-support/pom.xml
Outdated
<dependency> | ||
<groupId>${project.groupId}</groupId> | ||
<artifactId>refaster-runner</artifactId> | ||
<version>${project.version}</version> |
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 generally we use root's <dependencyManagement>
for managing internal modules' version (so together with next suggestion):
<version>${project.version}</version> |
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.
A few more points of feedback. Only RefasterCollectionTestUtil
to go, but did not review it yet as I expect a few changes based on the feedback. For other reviewers:
As discussed during the demo, @rickie will update RefasterCollectionTestUtil
to report line numbers and columns instead of the current positions (which is the character count).
@@ -0,0 +1,9 @@ | |||
package tech.picnic.errorprone.refaster.test; | |||
|
|||
final class MatchInWrongMethodTemplatesTest implements RefasterTemplateTestCase { |
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.
Just a bit of a thought here. It might be nice, especially when we open-source, as a convention to add class-level Javadoc to these test cases. This way, once the test collection grows, we can easily with human-readable text read what these test input-output files are for. Now it is slightly hard to oversee with 3 files per test-case.
Don't have a strong opinion on it, nor for its location, so feel free to do with this feedback what you want 😅
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.
Good one, will propose something. Let me know what you think :).
Can also be used to make the link between input and output clearer (at least for these resources).
/* Did not encounter test in /tech.picnic.errorprone.refaster.test.MissingTestAndWrongTestTemplatesTestInput.java for the following template(s): | ||
- TemplateWithoutTest |
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.
/tech.picnic.errorprone.refaster.test.MissingTestAndWrongTestTemplatesTestInput.java
feels a bit superfluous as this output file is connected to the input file. The test needs to be present in both (unless we extend Refaster to rename methods as well? 🤔). I'd consider removing the filename. I'd also consider indicating that we are missing a test method:
/* Did not encounter test in /tech.picnic.errorprone.refaster.test.MissingTestAndWrongTestTemplatesTestInput.java for the following template(s): | |
- TemplateWithoutTest | |
/* Did not encounter a test method for the following template(s): | |
- TemplateWithoutTest |
or even indicating which method we expect per template:
/* Did not encounter test in /tech.picnic.errorprone.refaster.test.MissingTestAndWrongTestTemplatesTestInput.java for the following template(s): | |
- TemplateWithoutTest | |
/* Did not encounter test methods for the following template(s): | |
- `testTemplateWithoutTest` for template `TemplateWithoutTest`. |
See also next comment related to this.
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.
as this output file is connected to the input file.
Yeah true, what I do like about mentioning the file, is that this points the user exactly to where they need to go and makes this connection clear. If a user is not 100% familiar with this setup it could help. OTOH I can see why removing it would also be clear enough 🤔.
I like the suggestions of making some messages more specific. The concern I have for some of them, is that strictly speaking they are not always "correct". Based on the implementation we can not always draw the conclusion like suggested here. Let me give an example:
/* Did not encounter test methods for the following template(s):
testTemplateWithoutTest
for templateTemplateWithoutTest
.
We don't verify this currently (again, strictly speaking). First, we use the classpath to collect all names of the Refaster templates of a collection. Next, we get a list of all the matches and compare this list to the list from the previous step. We can easily see that a template does not occur in the list of matches and we print out this message.
We could do something like (to be improved):
Did not encounter test code that matched the following template(s): [....] Please add a method named 'test' + the name of the template.
Whatever we decide, it is clear that we can improve the way in which we guide the developer based on the (error) messages 😄.
The reason for specifically mentioning MissingTestAndWrongTestTemplatesTestInput
is that it helps the developer do the first step, which is adding something in the input file. If someone already added a method in the output file but forgot the input file, there will be a different error message (as this is already handled by the EP test framework). It will look something like:
(Btw, this also holds for the case where something is something in the input but not in the output.)
expected:
boolean testTemplateWithoutTest() {
return "foo".length() == 0;
}
but was:
<not that method>
So once the developer added something to the input file the rest of the framework will "take care of the rest" and guide the developer further. WDYT?
Nonetheless, the full package name is not that useful so we can omit that for sure.
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.
On second thought, you are right. We should keep the name of the class in there. Looking at the test case, it isn't that interesting. But as this is console output, might be less visible that this is the problematic file indeed. Not keeping the package in there SGTM.
We don't verify this currently (again, strictly speaking). First, we use the classpath to collect all names of the Refaster templates of a collection. Next, we get a list of all the matches and compare this list to the list from the previous step. We can easily see that a template does not occur in the list of matches and we print out this message.
Regarding that, the implementation is indeed something I propose to change (see other comment). What I would do is separate this into two checks, for which the first is:
- "Use the classpath to collect all names of the Refaster templates of a collection"
- Get all the methods defined in the input test file.
- Require all templates to have a method
testTemplateX
. If not, print thisDid not encounter test method for the following template(s)
message.
Effectively, this is what currently is already enforced. So I thought it would be nicer to make this a more explicit initial simple check before we start looking at 'what templates have been matched in which test method?'.
Then for the second check, we can verify the following to produce the The following matches occurred in method ...
message:
- Does my
TemplateX
apply changes to thetestTemplateX
method? If not -> message. - Do templates other than
TemplateX
match ontestTemplateX
method? If so -> message.
I think this improves the developer experience and is quite a nice setup as the messages are more encapsulated/tied to what is verified.
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.
So I thought it would be nicer to make this a more explicit initial simple check before we start looking at 'what templates have been matched in which test method?'.
To give context to this thought of mine, see this test testcase for this template I wrote on my branch which has the suggestion applied for this review. Here it would've been nice to also have a message stating that we Did not encounter test method for the following template(s): StringEquals
(even though it matched unexpectedly in a test method targeted towards testing a different template). Of course, after fixing this unexpected match, another run of the tests would fail with this 'Did not encounter ...' message. So all in all, happy to keep current implementation too 🙂
/* The following matches occurred in method `testWrongName` (position: [131,233]): | ||
- Template `StringIsEmpty` matched on position: [161..177) | ||
- Template `StringIsEmpty` matched on position: [183..199) | ||
- Template `StringIsEmpty` matched on position: [212..228) | ||
*/ |
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.
Having a bit of trouble giving feedback on this to come up with a suggestion. My initial thought was that this is a bit generic non-actionable feedback. It might be nice to point out what is wrong or steer the devs in a certain direction instead.
In my mind this type of feedback currently can happen in three cases (given the fact that we match templates on method name in tests):
- A template unexpectedly matches on a test method meant for another template. Think for example about a new introduced template that matches a subset of the cases for an already existing template. Then the new narrower-scoped template could change an existing test targeted towards the broader-scoped template. The developer should resolve the overlap in templates, maybe.
- A template matches a test method for auxiliary use (e.g. helper methods). This should just be fixed in the
XInput
file. - The method name is wrong, as tested here. It should be renamed.
The third case is not distinguishable from the second apart from our own interpretation of the test code. Therefore, I'd prefer also a Did not encounter test method for the following template(s)
message (see the other comment). I think we can achieve this by simply looking at (the lack of) methods defined instead of templatesWithoutMatch
.
For the other two cases, I think this message is indeed nice to have a message indicating that we unexpectedly found a match in the code for a specific template. Not sure about any indication of why we did not expect it. Maybe by just adding the word unexpectedly
, but might be nice to give further reason. WDYT?
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.
Oh nice, I really like the word unexpectedly
.
The developer should resolve the overlap in templates, maybe.
Yes for sure, otherwise the self-check will not succeed 😉.
Good observations, thought quite some time about it now.
If we would change the message to the next line, I think we would cover all cases (and be clear with regards of guiding the developer):
Template 'StringIsEmpty' matched on line 15, expected to match in a method named 'testStringIsEmpty'
.
(Combined reply on the new comment)
I think this improves the developer experience and is quite a nice setup as the messages are more encapsulated/tied to what is verified.
This is true, will think about it and discuss it.
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.
Currently, the main reason for adding these checks is to help ourselves by making sure that the Refaster templates are tested and tested in the right place.
Additionally, we want to make sure that the tests of the existing body of templates are correct.
Finally, this will help us with doing reviews of new PRs in the future easier (also for contributors outside of Picnic).
So for now, I want to argue that with improving the error messages the current implementation would be sufficient for our needs.
Based on the new error messages (to be pushed) all cases are sufficiently covered IMHO.
If we later feel that it is necessary to change or improve the checks, we can always do that.
For example, in the case that we get many contributions or developers find the development confusing, we can always choose to add this distinction in the error message.
Based on the content of the PR and the feedback (also from the demo) I feel that it could help to point out the following (also to explain to other reviewers) 😄. We primarily rely on the test framework provided by Error Prone. In The validation that we add is where the validation of the framework "stops" but where we want to be sure that (for example) specific cases are handled / tested. This means that what we validate could, in some cases, be quite specific. |
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.
Very cool change!
I have very little knowledge about how this works and spent most of the time trying to understand the code, so I am finding very difficult to give useful feedback :)
I don't know if it would be applicable to this type of class, specially given the stuff from javac - but is it possible to split the classes to unit test them?
If we are planning on open sourcing this, should we also add a README file describing how to use this new feature?
very nice tests btw!
name = "RefasterTestBugChecker", | ||
summary = "Validate a Refaster template collection and its tests", | ||
severity = ERROR) | ||
public static final class RefasterTestBugChecker extends BugChecker |
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.
is there any specific reason to not split this into a separate file?
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.
We use this setup in refaster-support
currently. However, there we have small checks that are in the same class. This checker is now pretty big and deserves it's own class, so will move it!
return fqcn.substring(fqcn.lastIndexOf('.') + 1); | ||
} | ||
|
||
private class ValidateMatchesInMethodsScanner extends TreeScanner<Void, VisitorState> { |
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.
same for this class :)
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.
This one I wouldn't move to it's own class. In Error Prone (so in the upstream repo) this is how Visitors
and Scanners
are often used. They are in most cases specific to the BugChecker
and almost always live in the class of the check. I propose we do the same here 😄.
|
||
JCCompilationUnit compilationUnit = (JCCompilationUnit) tree; | ||
ImmutableRangeMap<Integer, String> matchesRangeMap = | ||
buildRangeMapForMatches(matches, compilationUnit.endPositions); |
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 saw that the compilationUnit.endPositions
is initialised with null, does this happen in real scenarios?
I don't know how this works IRL :)
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.
Ah good catch! This is something that I had to work with during my thesis.
Looking at the usage of this field, we see (among others) the following classes that can put something in this field:
- JavaCompiler.java
- JavacTrees.java
- JavacParser.java
This is something that the compiler and parser will handle for us. So we don't need to worry about it being null
😄.
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.
Went through it all. Really cool work! Got a few more comments.
As said in last comments, have local changes that I can push for them if you want. Pushed them to a seperate branch: see diff.
...t-support/src/main/java/tech/picnic/errorprone/refaster/test/RefasterCollectionTestUtil.java
Outdated
Show resolved
Hide resolved
* | ||
* @param clazz The Refaster template collection under test. | ||
*/ | ||
public static void validateTemplateCollection(Class<?> clazz) { |
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.
Just a suggestion, comes down to style preference maybe. Generally, I prefer to extract this form of variable initialization to its own method, if sensible. Here, I am doubtful but leaning towards extracting it to deduplicate receiving content for two files as well. What it could look like if we do so:
public static void validateTemplateCollection(Class<?> clazz) {
String className = clazz.getSimpleName();
BugCheckerRefactoringTestHelper.newInstance(
RefasterTestBugChecker.class, RefasterCollectionTestUtil.class)
.setArgs(ImmutableList.of("-XepOpt:RefasterTestChecker:TemplateCollection=" + className))
.addInputLines(
clazz.getName() + "TestInput.java",
getContentOfResource(clazz, className + "TestInput.java"))
.addOutputLines(
clazz.getName() + "TestOutput.java",
getContentOfResource(clazz, className + "TestOutput.java"))
.doTest(TEXT_MATCH);
}
private static String getContentOfResource(Class<?> clazz, String resource) {
JavaFileObject object = FileObjects.forResource(clazz, resource);
try {
return object.getCharContent(false).toString();
} catch (IOException e) {
throw new IllegalStateException("Can't retrieve content for file " + resource, e);
}
}
Note, changed the exception message as we can now just point to the problematic file instead.
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.
For context, ideally, we want to propose this simple change to google/error-prone
. It would make this method a lot nicer because we can just pass the JavaFileObject
s directly. We can significantly improve this method if they accept that change upstream.
Having said that, I like the suggestion 😄 although the instantiation of the BugChecker is a bit big in that case 🤔 . Not sure how to improve, nice suggestion 🚀 !
private ImmutableSet<String> getTemplateNamesWithoutMatch(List<Description> matches) { | ||
ImmutableSet<String> templateNamesOfMatches = | ||
matches.stream() | ||
.map(description -> description.checkName) | ||
.map(RefasterTestBugChecker::getNameFromFQCN) | ||
.collect(toImmutableSet()); | ||
|
||
return Sets.difference(templateNamesFromClassPath, templateNamesOfMatches).immutableCopy(); | ||
} |
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.
We can reuse the matchesRangeMap
as this already contains the FQCN of the matched templates. You could also decide to inline this, but that does not make it much more readable. Suggestion:
private ImmutableSet<String> getTemplateNamesWithoutMatch(List<Description> matches) { | |
ImmutableSet<String> templateNamesOfMatches = | |
matches.stream() | |
.map(description -> description.checkName) | |
.map(RefasterTestBugChecker::getNameFromFQCN) | |
.collect(toImmutableSet()); | |
return Sets.difference(templateNamesFromClassPath, templateNamesOfMatches).immutableCopy(); | |
} | |
private ImmutableSet<String> getTemplateNamesWithoutMatch( | |
ImmutableRangeMap<Integer, String> matchesRangeMap) { | |
return Sets.difference( | |
templateNamesFromClassPath, | |
ImmutableSet.copyOf(matchesRangeMap.asMapOfRanges().values())) | |
.immutableCopy(); | |
} |
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.
Nice idea, I tweaked it a bit. WDYT of passing a ImmutableCollection
. It feels a bit too specific to pass the full ImmutableRangeMap
, what if we make it a ImmutableCollection
? We can say "hey method here is a collection, what are templates without match"?
(Pushing suggestion once I went over all feedback)
private void appendCommentToCompilationUnit(String message, String list, VisitorState state) { | ||
String comment = String.format("\n/* %s:%s*/", message, list); | ||
CompilationUnitTree compilationUnit = state.getPath().getCompilationUnit(); | ||
state.reportMatch( | ||
describeMatch(compilationUnit, SuggestedFix.postfixWith(compilationUnit, comment))); | ||
} |
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 it would look cleaner to do the following. This also causes more presentation logic to be isolated in here.
- Make parameter
list
aStream<String>
instead of a formatted String. - Call this stream
conflicts
or something,list
is a bit too non-descriptive to my taste. - Collect in here and inline the collector as this is the only usage.
- Don't have prefix and suffix in collector as we should always have at least one element and we can put it in the main
String.format
instead.
Resulting in:
private void appendCommentToCompilationUnit(String message, String list, VisitorState state) { | |
String comment = String.format("\n/* %s:%s*/", message, list); | |
CompilationUnitTree compilationUnit = state.getPath().getCompilationUnit(); | |
state.reportMatch( | |
describeMatch(compilationUnit, SuggestedFix.postfixWith(compilationUnit, comment))); | |
} | |
private void appendCommentToCompilationUnit( | |
String message, Stream<String> conflicts, VisitorState state) { | |
String comment = | |
String.format("\n/* %s:\n- %s\n*/", message, conflicts.collect(joining("\n- "))); | |
CompilationUnitTree compilationUnit = state.getPath().getCompilationUnit(); | |
state.reportMatch( | |
describeMatch(compilationUnit, SuggestedFix.postfixWith(compilationUnit, comment))); | |
} |
Feel free to adopt a subset of these suggestions 😄
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.
The reason for having the collector like this is that (IMO) it makes the first parameter of the String.format
a bit easier to read and understand. Probably a preference thingy, we could see what other reviewers think 👀.
Agree with all the other feedback! Will push something.
boolean correctTemplatesMatchedInMethod = | ||
matchesInCurrentMethod.asMapOfRanges().values().stream().allMatch(methodName::equals); | ||
if (!correctTemplatesMatchedInMethod) { | ||
appendCommentToCompilationUnit( |
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.
We could pass in tree
here to place these suggestions postfix the violating method instead of postfix the end of the compilation unit (for the other usage we can just pass compilationUnit
). This might make it easier for huge Input/Output
files to see where you need to change things.
So that would result in appendCommentToCompilationUnit
:
state.reportMatch(
describeMatch(
state.getPath().getCompilationUnit(), SuggestedFix.postfixWith(unit, comment)));
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.
Discussed this briefly during the stand-up. Very good idea! Based on how the output is generated (and taking into account long test methods), we could also prefix the method with the comment. As a result, we also see the method name instead of a few test cases which can be harder to track. Based on the provided diff with small tweaks we get this as a warning if we run the test (which looks awesome 🚀 !) :
+ /* The following matches unexpectedly occurred in method `testWrongName`:
+ - Template `StringIsEmpty` matches on line 6, while it should match in a method named `testStringIsEmpty`.
+ - Template `StringIsEmpty` matches on line 7, while it should match in a method named `testStringIsEmpty`.
+ - Template `StringIsEmpty` matches on line 8, while it should match in a method named `testStringIsEmpty`.
+ */
boolean testWrongName() {
"foo".isEmpty();
"bar".isEmpty();
In the output files we add these comments to validate the RefasterCollectionTestUtil
"extension". It is important to note that the shown line numbers won't match the correct line number in the output files that are used to test the extension (the resources that live in refaster-test-support
under test/resources
).
However, we are not supposed to write these comments as a developer because we need to fix this warning and not add them in the output file to let the build pass. For that reason the line numbers look incorrect, but what we are now validating is not someone should do. I'm not sure if I'm explaining it clearly, let me know if it is still unclear :D.
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.
Nice! Agreed. Prefix looks even better 🚀.
Haha, yes clear. To clarify for other reviewers maybe I'll try to approach it from a different point of view. Important to note is that this output will be shown in console output when running tests. Therefore the developer will be searching for the file and the line numbers will match. For the purpose of testing RefasterCollectionTestUtil
, we verify that it does match this output, hence why in this case the line numbers appear off by the added comments.
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.
@rickie it might perhaps be nice to document this with one or two sentences in RefasterCollectionTestUtilTest.java
.
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.
Good one, pushed a suggestion. Suggestions welcome of course 😉.
matchesRangeMap.asMapOfRanges().entrySet().stream() | ||
.map( |
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.
We should filter here those that are correct (I have local changes for all suggestions including a testcase for this, let me know if you want me to push it or send it to you Pushed them to a seperate branch: see diff):
matchesRangeMap.asMapOfRanges().entrySet().stream() | |
.map( | |
matchesRangeMap.asMapOfRanges().entrySet().stream() | |
.filter(e -> !e.getValue().equals(methodName)) | |
.map( |
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.
Good catch! Used the diff to add an extra test case 🥳.
bb49a9e
to
1c7b580
Compare
Thanks for all the suggestions! Addressed all the feedback by now. Will work on a Decided to push the changes already to make the code ready for the next round of feedback 😉. |
b607643
to
f08b3b0
Compare
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.
Nice documentation 👍 That will help in onboarding.
refaster-test-support/README.md
Outdated
template collection. This test utility applies the Refaster templates in the collection to a provided input file, and | ||
expects the result to exactly match the contents of a provided output file. |
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.
This test utility applies the Refaster templates in the collection to a provided input file, and
expects the result to exactly match the contents of a provided output file.
Is a bit too similar to the following the paragraph before:
The Refaster templates from the collection are applied on the input file and should exactly match the content of
the provided output file.
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'm not sure if this repetition is bad. The first part of the paragraph summarizes all the following content. It seemed nice to give the reader a summary of what it will read. Perhaps it is not that useful.
refaster-test-support/README.md
Outdated
template collection must match the naming convention `<TemplateCollectionClassName>Templates.java`. | ||
- An input file matching the naming convention `<TemplateCollectionClassName>TemplatesTestInput.java` is added for every | ||
template collection. | ||
- An output file matching the naming convention `<TemplateCollectionClassName>TemplatesTestOutput.java` |
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.
Technically, <TemplateCollectionClassName>Templates.java
is the template collection's class name, right? 🤔
template collection must match the naming convention `<TemplateCollectionClassName>Templates.java`. | |
- An input file matching the naming convention `<TemplateCollectionClassName>TemplatesTestInput.java` is added for every | |
template collection. | |
- An output file matching the naming convention `<TemplateCollectionClassName>TemplatesTestOutput.java` | |
template collection must match the naming convention `<TemplateCollectionName>Templates.java`. | |
- An input file matching the naming convention `<TemplateCollectionName>TemplatesTestInput.java` is added for every | |
template collection. | |
- An output file matching the naming convention `<TemplateCollectionName>TemplatesTestOutput.java` |
refaster-test-support/README.md
Outdated
template collection. | ||
- An output file matching the naming convention `<TemplateCollectionClassName>TemplatesTestOutput.java` | ||
file is added for every template collection. | ||
- For each Refaster template in the collection, the input and output file contain a method. The name of the method is |
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.
- For each Refaster template in the collection, the input and output file contain a method. The name of the method is | |
- For each Refaster template in the collection, the input and output file must contain a method. The name of the method is |
refaster-test-support/README.md
Outdated
- The method contains at least one expression that matches the `@BeforeTemplate`. As a result, the output file contains | ||
the same method with an updated expression, matching the content of the `@AfterTemplate`. |
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.
Maybe also mention that no other templates must match? Could not find the right words for a suggestion 🤔
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.
Good one, will push a proposal.
refaster-test-support/README.md
Outdated
|
||
As a result from these tests, unexpected output will be shown in the console. | ||
|
||
An example of a folder structure for such a setup: |
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.
Preference thing, a bit nicer to read IMO.
An example of a folder structure for such a setup: | |
An example of a folder structure for such a setup is as follows: |
refaster-test-support/README.md
Outdated
└── ExampleTemplatesTestInput.java -- Contains a class named `ExampleTemplatesTest` | ||
└── ExampleTemplatesTestOutput.java -- Contains a class named `ExampleTemplatesTest` |
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.
Two remarks:
- For consistency, end the comments with a dot (we currently do that for the
RefasterCollectionTest
line). - Might be nice to give an example of the methods too.
Did not pay attention to formatting for line column width, so maybe this suggestion isn't as 'nice' to apply.
└── ExampleTemplatesTestInput.java -- Contains a class named `ExampleTemplatesTest` | |
└── ExampleTemplatesTestOutput.java -- Contains a class named `ExampleTemplatesTest` | |
└── ExampleTemplatesTestInput.java -- Contains a class named `ExampleTemplatesTest` and two methods named `testExample1Template` and `testExample2Template`. | |
└── ExampleTemplatesTestOutput.java -- Contains a class named `ExampleTemplatesTest` and two methods named `testExample1Template` and `testExample2Template`. |
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.
Good one, makes it really clear for the reader. W.r.t. linewrapping, I'm not sure how to proceed here, in general I mean. I think the max of 80 is used in other repositories. I couldn't find a nice guideline for this. That's why I used the current formatting I have in IntelliJ... Ideas on this are welcome 😉.
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.
(Made sure to wrap at 79 as that is our convention for README.md
s).
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.
Pushed two minor tweaks. LGTM 🚀
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.
looks awesome to me :)
|
||
An example of a folder structure for such a setup is as follows: | ||
|
||
``` |
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.
noice example :)
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.
looks awesome to me :)
b89118c
to
77b3b70
Compare
Rebased. |
77b3b70
to
f8119a4
Compare
52c1d9e
to
bc48dc2
Compare
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.
Added a small commit. I noticed that the Refaster templates are now no longer tested (notice the shorter build time). And the self-check build also isn't slower, which makes me suspect that the Refaster templates aren't executed at all. That requires some investigation.
pom.xml
Outdated
<module>refaster-resource-compiler</module> | ||
<module>refaster-runner</module> |
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.
For consistency, should we s/refaster-resource-compiler/refaster-compiler/
? 🤔
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.
Good one, created #110!
5b49655
to
53ffe2b
Compare
Added a commit with a Javadoc tweak. Only open point from my side is a review of the README. |
Haha, looking forward to the results 👀. |
There were complex conflicts, so I solved them using a merge commit. Also added another tiny cleanup commit. README review is still TBD. |
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.
Hehe I see @Stephan202 also is taking a look at the README.md
now 😄 Flushing comments I had. Will commit those on paragraph @Stephan202 did not yet touch and reread the changed paragraphs while taking earlier comments in mind.
refaster-test-support/README.md
Outdated
|
||
## What does this module do? | ||
|
||
These utilities allow validating the rewrites (or their absence) performed by |
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 the following is more grammatically correct/reads nicer:
These utilities allow validating the rewrites (or their absence) performed by | |
These utilities allow for validating the rewrites (or absence thereof) as performed by |
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.
Applied.
refaster-test-support/README.md
Outdated
it matches and transforms code as intended. If a Refaster template is not | ||
covered by a test, if it influences unrelated test code, or if the associated | ||
test doesn't follow certain established standards, then this irregularity will | ||
be reported, and the associated template collection test will fail. This way |
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.
Committed
be reported, and the associated template collection test will fail. This way | |
be reported, and the associated template collection test will fail. This way, |
refaster-test-support/README.md
Outdated
A class that contains one or more Refaster templates is called a Refaster | ||
template collection. In a nutshell, to test a Refaster template collection | ||
class using `RefasterTemplateCollection`, one should create suitably named | ||
input and output files. The collection's Refaster templates are applied to the |
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.
Maybe a bit too explicit, but nowhere in this paragraph we have mentioned what is in these input or output files.
input and output files. The collection's Refaster templates are applied to the | |
input and output source code files. The collection's Refaster templates are applied to the |
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.
Will leave this one to @Stephan202 .
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.
Done :)
refaster-test-support/README.md
Outdated
templates in the collection to a provided input file, and expects the result | ||
to exactly match the contents of a provided output file. | ||
|
||
To adopt this setup, the following requirements have to be met: |
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.
Committed
To adopt this setup, the following requirements have to be met: | |
To adopt this setup, the following requirements must be met: |
refaster-test-support/README.md
Outdated
- Create a class with a (parameterized) test method that invokes | ||
`RefasterTemplateCollection#validate` and passes the collection(s) to | ||
validate. The Refaster template collection must match the naming convention | ||
`<TemplateCollectionName>Templates.java`. |
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.
Committed and reflowed
A few suggestions on this line. This suggestion makes the narrative more in line with 'requirements must be met' and the other items below w.r.t. 'is added'.
- Create a class with a (parameterized) test method that invokes | |
`RefasterTemplateCollection#validate` and passes the collection(s) to | |
validate. The Refaster template collection must match the naming convention | |
`<TemplateCollectionName>Templates.java`. | |
- A class with a (parameterized) test method that invokes | |
`RefasterTemplateCollection#validate` is created which provides the collection(s) to | |
validate. The Refaster template collection must match the naming convention | |
`<TemplateCollectionName>Templates.java`. |
refaster-test-support/README.md
Outdated
template collection. | ||
- For every Refaster template in the collection, the input and output file must | ||
contain a method. The name of the method is equal to the name of the Refaster | ||
template prefixed with `test` (e.g. `test<RefasterTemplateClassName>`). |
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.
Committed
template prefixed with `test` (e.g. `test<RefasterTemplateClassName>`). | |
template prefixed with `test` (e.g. `test<RefasterTemplateInnerClassName>`). |
Maybe to avoid confusion with the template collection class?
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.
TBH, to me, this one is not a clear improvement.
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.
Feel free to revert or change to something else if you don't agree. I can understand where you're coming from.
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.
Will do :). I like the suggestions in general 😄 👍🏻.
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.
Reverted, but was mainly giving my opinion to see what other reviewers think. That's why I commented in the first place.
refaster-test-support/README.md
Outdated
contain a method. The name of the method is equal to the name of the Refaster | ||
template prefixed with `test` (e.g. `test<RefasterTemplateClassName>`). | ||
- The method contains at least one expression that matches the | ||
`@BeforeTemplate` of one specific Refaster template. As a result, the output |
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.
Committed and reflowed
`@BeforeTemplate` of one specific Refaster template. As a result, the output | |
`@BeforeTemplate` of the corresponding Refaster template. As a result, the output |
The test enforces the exact refaster template to match right? Not just any refaster template in the collection?
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.
Currently looking at RefasterTemplateCollection.java
, flushing comments already.
@@ -0,0 +1,4 @@ | |||
/** Classes used to locate and apply compiled Refaster templates on. */ |
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.
Not sure if we want to have an intentional 1-to-1 mapping between the pom.xml
's description
and this package-info.java
(we did so for refaster-test-support
), but this one is currently not the same. I must say, I prefer the pom.xml
's description over this and would be in favor of replacing it.
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.
Good one!
/* | ||
* ERROR: The following matches unexpectedly occurred in method `testWrongName`: | ||
* - Template `StringIsEmpty` matches on line 6, while it should match in a method named `testStringIsEmpty`. | ||
* - Template `StringIsEmpty` matches on line 7, while it should match in a method named `testStringIsEmpty`. | ||
* - Template `StringIsEmpty` matches on line 8, while it should match in a method named `testStringIsEmpty`. | ||
*/ | ||
boolean testWrongName() { | ||
"foo".isEmpty(); | ||
"bar".isEmpty(); | ||
return "baz".isEmpty(); | ||
} | ||
} |
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.
This is already tested with MatchInWrongMethodTemplatesTestOutput.java
, isn't it? 🤔
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.
Strictly speaking yes, but it is to have something here as well. Also to see if it behaves correctly if the two situations are combined. So is the error still correct if there is a test missing and this method has some wrong entries.
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.
So I'd suggest to leave it as is.
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.
Ah makes sense. Might be nice to reflect that in the main template collection's JavaDoc, but I agree, asserting the combination is nice 👍
import javax.annotation.Nullable; | ||
|
||
/** Refaster template collection to validate that having no violations works as expected. */ | ||
final class ValidTemplates { |
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.
Would it be nice to add a template containing a Refaster.anyOf
in its before
? I know we won't ascertain all branches to be fulfilled, but at least knowing the collection is capable of reading one, might be nice.
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.
Leaving this decision to @rickie.
(I'm fine deferring it because the checker currently doesn't do anything with Refaster.anyOf
, so indeed strictly speaking it doesn't add much.)
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'd also like to postpone this 😄.
(Good point though 😉)
/** | ||
* A {@link BugChecker} that applies a Refaster template collection to an associated test input file | ||
* by delegating to the {@link Refaster} checker, and subsequently validates that each template | ||
* modifies exactly one distinct method, as indicated by each method's name. |
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.
The name of the template enforces the name of the test method, so this would be more correct, right?
Also, missing some documentation that the input method should be prefixed with test
.
Having a hard time to come up with a suggestion (especially as it is all one line now and my brain is a bit depleted), but here we go:
* modifies exactly one distinct method, as indicated by each method's name. | |
* modifies exactly one distinct method, as identified by the corresponding template's name and prefixed with `test`. |
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 we should start a new paragraph ;). Will propose something.
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.
Amazing PR and definitely a fun one to review. Also since my last review, the code became even nicer and easily readable. Thanks a lot for all the hard effort @rickie and @Stephan202 🙏 Definitely one to be proud of. Unfortunately don't have the time to post a suggested commit message, but I trust you'll get a good one out of it. Enjoy the first release, and make sure to celebrate it with the entire team!
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.
Added a commit; README review is still TBD.
@@ -0,0 +1,4 @@ | |||
/** Classes used to locate and apply compiled Refaster templates on. */ |
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.
Good one!
import javax.annotation.Nullable; | ||
|
||
/** Refaster template collection to validate that having no violations works as expected. */ | ||
final class ValidTemplates { |
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.
Leaving this decision to @rickie.
(I'm fine deferring it because the checker currently doesn't do anything with Refaster.anyOf
, so indeed strictly speaking it doesn't add much.)
/** | ||
* A {@link BugChecker} that applies a Refaster template collection to an associated test input file | ||
* by delegating to the {@link Refaster} checker, and subsequently validates that each template | ||
* modifies exactly one distinct method, as indicated by each method's name. |
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 we should start a new paragraph ;). Will propose something.
Bit late for a response, but the latest changes LGTM! |
Added a commit; PTAL. |
Nice improvements. Looks really good 👍🏻. |
Added one more commit. @rickie do we already have a suggested commit message? |
I'll write one now! @Stephan202 |
Suggested commit message:
|
^ Tweaked it. Have a meeting now; will do another pass later. |
❗
This branch is now on top of #113❗New method:
RefasterTemplateCollectionValidator#validate
.This can verify that all Refaster templates from a given template
collection are covered by at least one test and that the match rewrites
code in the correct test method.
Introduce the following modules:
refaster-runner
refaster-test-support
We can use this validation in the future to be more certain about new PRs, as this can guarantee, to some extent, that Refaster templates are properly tested.
Notes
The goal of the validator is to help a developer write Refaster templates and the tests for the template. We want every template to have a test and verify that Refaster matches in the place that we expect it to match.