Skip to content

feat: Implement conversion of diff content to ReviewDog format #2478

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

YongGoose
Copy link

@YongGoose YongGoose commented May 9, 2025

Related issue: #655

Copy link
Member

@nedtwigg nedtwigg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting a draft PR is a great approach!

The Gradle tests are quite slow. I would create a ReviewDogGenerator in the lib-extra project, running tests there is much faster than in the Gradle project. Once we can generate a ReviewDog file, then we can wire it up with Gradle.

As for the wiring, this is how it works now

graph TD
    spotlessJava --> spotlessJavaCheck
    spotlessJava --> spotlessJavaApply
    spotlessJavaCheck --> spotlessCheck
    spotlessJavaApply --> spotlessApply

    spotlessKotlin --> spotlessKotlinCheck
    spotlessKotlin --> spotlessKotlinApply
    spotlessKotlinCheck --> spotlessCheck
    spotlessKotlinApply --> spotlessApply
Loading

All of the work happens in spotlessJava, and it happens in a way which supports caching and up-to-dateness, etc

@TaskAction
public void performAction(InputChanges inputs) throws Exception {
IdeHook.State ideHook = getIdeHookState().getOrNull();
if (ideHook != null && ideHook.path != null) {
IdeHook.performHook(this, ideHook);
return;
}
SpotlessTaskService taskService = getTaskService().get();
taskService.registerSourceAlreadyRan(this);
if (target == null) {
throw new GradleException("You must specify 'Iterable<File> target'");
}
if (!inputs.isIncremental()) {
getLogger().info("Not incremental: removing prior outputs");
getFs().delete(d -> d.delete(cleanDirectory));
getFs().delete(d -> d.delete(lintsDirectory));
Files.createDirectories(cleanDirectory.toPath());
Files.createDirectories(lintsDirectory.toPath());
}

Then spotlessJavaCheck and spotlessJavaApply just look at those folders and copy them around

private void performAction(boolean isTest) throws IOException {
ConfigurableFileTree cleanFiles = getConfigCacheWorkaround().fileTree().from(getSpotlessCleanDirectory().get());
ConfigurableFileTree lintsFiles = getConfigCacheWorkaround().fileTree().from(getSpotlessLintsDirectory().get());
if (cleanFiles.isEmpty() && lintsFiles.isEmpty()) {
getState().setDidWork(sourceDidWork());
} else if (!isTest && applyHasRun()) {
// if our matching apply has already run, then we don't need to do anything
getState().setDidWork(false);
} else {
List<File> unformattedFiles = getUncleanFiles(cleanFiles);

public void performAction() {
getTaskService().get().registerApplyAlreadyRan(this);
ConfigurableFileTree cleanFiles = getConfigCacheWorkaround().fileTree().from(getSpotlessCleanDirectory().get());
ConfigurableFileTree lintsFiles = getConfigCacheWorkaround().fileTree().from(getSpotlessLintsDirectory().get());
if (cleanFiles.isEmpty() && lintsFiles.isEmpty()) {
getState().setDidWork(sourceDidWork());
} else {

I would expect spotlessReviewDog to work in that same structure. But probably we should get the guts working in lib-extra, and also write some docs for plugin-gradle, before we spend too much time implementing the wiring.

task.setGroup(TASK_GROUP);
task.mustRunAfter(BasePlugin.CLEAN_TASK_NAME);
});
rootCheckTask.configure(task -> task.dependsOn(diffTask));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think everybody needs the diff task.

@YongGoose
Copy link
Author

YongGoose commented May 11, 2025

@nedtwigg

I’m planning to implement this feature in three steps:

  1. Create the ReviewDogGenerator class
  2. Add a task in the Gradle-plugin that uses the information stored by ReviewDogGenerator
  3. Write test codes

This dc52b26 includes only the implementation of step 1.

Also, I have a question!

After ReviewDogGenerator generates a diff for ReviewDog, I’d like to store that information in a separate directory (like SpotlessTaskImpl does).
However, it seems that classes from gradle.api can’t be used within the lib-extra directory.

Would you be able to offer some guidance on this?

@YongGoose YongGoose requested a review from nedtwigg May 11, 2025 12:19
@nedtwigg
Copy link
Member

nedtwigg commented May 12, 2025

Here is my suggestion:

class ReviewDog {
  public static String rdjsonlDiff(String path, String actualContent, String formattedContent)
  public static String rdjsonlLints(String path, String formattedContent, List<FormatterStep> steps, List<List<Lint>> lintsPerStep)
}

You can test this easily in lib-extra

class ReviewDogTest {
  @Test
  public void diffSingleLine() {
    expectSelfie(ReviewDog.rdjsonlDiff("test.txt", "dirty", "clean")).toBe_TODO()
  }
  ... etc
}

So you can build and test the ReviewDog features in isolation, no gradle API required. Once these are working, you can pipe them together in a Gradle task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants