Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 29 additions & 41 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,74 +5,62 @@ on:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
issues:
types: [opened, assigned]

jobs:
check-team-membership:
claude:
# Only run if @claude is mentioned in the triggering content
# For issues (opened/assigned), checks the issue body or title
# For comments/reviews, checks the comment/review body
if: contains(github.event.comment.body || github.event.review.body || github.event.issue.body || github.event.issue.title || '', '@claude')
runs-on: ubuntu-latest
outputs:
is-team-member: ${{ steps.check-membership.outputs.is-member }}
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Check team membership
id: check-membership
uses: actions/github-script@v8
with:
script: |
try {
// Get username - prioritize sender (the person who triggered the event)
const username = github.event?.sender?.login ||
github.event?.comment?.user?.login;

// Get the user who triggered the event
const username = context.payload.sender?.login;

if (!username) {
console.log('Could not determine username from event payload');
console.log(`Event type: ${github.event_name}`);
console.log(`Event payload keys: ${Object.keys(github.event).join(', ')}`);
return false;
core.setFailed('Could not determine username from event');
return;
}

console.log(`Checking team membership for user: ${username} (triggered by ${github.event_name} event)`);

console.log(`Checking if ${username} is a member of diffplug/spotless`);
const { data } = await github.rest.teams.getMembershipForUserInOrg({
org: 'diffplug',
team_slug: 'spotless',
username: username
});
console.log(`User ${username} membership status: ${data.state}`);
return data.state === 'active';

if (data.state !== 'active') {
core.setFailed(`User ${username} is not an active team member`);
} else {
console.log(`✓ ${username} is an active team member`);
}
} catch (error) {
const username = github.event.sender?.login || github.event.comment?.user?.login || 'unknown user';
console.log(`User ${username} is not a member of the Spotless team or error occurred: ${error.message}`);
return false;
// User is not a team member or API error
core.setFailed(`Access denied: ${error.message}`);
}

claude:
needs: check-team-membership
if: |
needs.check-team-membership.outputs.is-team-member == 'true' &&
(
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
)
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
46 changes: 6 additions & 40 deletions gradle/rewrite.gradle
Original file line number Diff line number Diff line change
@@ -1,46 +1,9 @@
apply plugin: 'org.openrewrite.rewrite'

rewrite {
activeRecipe(
'org.openrewrite.gradle.GradleBestPractices',
'org.openrewrite.java.RemoveUnusedImports',
'org.openrewrite.java.format.RemoveTrailingWhitespace',
'org.openrewrite.java.migrate.UpgradeToJava17',
'org.openrewrite.java.recipes.JavaRecipeBestPractices',
'org.openrewrite.java.recipes.RecipeTestingBestPractices',
'org.openrewrite.java.security.JavaSecurityBestPractices',
'org.openrewrite.staticanalysis.EqualsAvoidsNull',
'org.openrewrite.staticanalysis.JavaApiBestPractices',
'org.openrewrite.staticanalysis.LowercasePackage',
'org.openrewrite.staticanalysis.MissingOverrideAnnotation',
'org.openrewrite.staticanalysis.ModifierOrder',
'org.openrewrite.staticanalysis.NoFinalizer',
'org.openrewrite.staticanalysis.NoToStringOnStringType',
'org.openrewrite.staticanalysis.NoValueOfOnStringType',
'org.openrewrite.staticanalysis.RemoveUnusedLocalVariables',
'org.openrewrite.staticanalysis.RemoveUnusedPrivateFields',
'org.openrewrite.staticanalysis.RemoveUnusedPrivateMethods',
'org.openrewrite.staticanalysis.UnnecessaryCloseInTryWithResources',
'org.openrewrite.staticanalysis.UnnecessaryExplicitTypeArguments',
'org.openrewrite.staticanalysis.UnnecessaryParentheses',
'org.openrewrite.staticanalysis.UnnecessaryReturnAsLastStatement',
'tech.picnic.errorprone.refasterrules.BigDecimalRulesRecipes',
'tech.picnic.errorprone.refasterrules.CharSequenceRulesRecipes',
'tech.picnic.errorprone.refasterrules.ClassRulesRecipes',
'tech.picnic.errorprone.refasterrules.CollectionRulesRecipes',
'tech.picnic.errorprone.refasterrules.ComparatorRulesRecipes',
'tech.picnic.errorprone.refasterrules.FileRulesRecipes',
'tech.picnic.errorprone.refasterrules.MicrometerRulesRecipes',
'tech.picnic.errorprone.refasterrules.PatternRulesRecipes',
'tech.picnic.errorprone.refasterrules.PreconditionsRulesRecipes',
'tech.picnic.errorprone.refasterrules.PrimitiveRulesRecipes',
'tech.picnic.errorprone.refasterrules.StreamRulesRecipes',
'tech.picnic.errorprone.refasterrules.TimeRulesRecipes'
//'org.openrewrite.staticanalysis.CodeCleanup', bug
//'org.openrewrite.staticanalysis.CommonStaticAnalysis', bug
//'org.openrewrite.staticanalysis.UnnecessaryThrows', bug
)
activeRecipe('org.openrewrite.java.format.NoWhitespaceBefore')
exclusions.addAll(
'**.dirty.java',
'**_gradle_node_plugin_example_**',
'**gradle/changelog.gradle',
'**gradle/java-publish.gradle',
Expand All @@ -50,7 +13,10 @@ rewrite {
'**lib/build.gradle',
'**package-info.java',
'**plugin-maven/build.gradle',
'**settings.gradle'
'**settings.gradle',
'**special-tests.gradle',
'**FormatterProperties.java',
'**testlib/src/main/resources**'
)
exportDatatables = true
failOnDryRunResults = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,15 @@ public boolean errorsDetected() {
synchronized (GroovyLogManager.manager) {
GroovyLogManager.manager.removeLogger(this);
}
return 0 != errors.size();
return !errors.isEmpty();
}

@Override
public String toString() {
StringBuilder string = new StringBuilder();
if (1 < errors.size()) {
string.append("Multiple problems detected during step execution:");
} else if (0 == errors.size()) {
} else if (errors.isEmpty()) {
string.append("Step sucesfully executed.");
}
for (Throwable error : errors) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,26 @@ private int category(BodyDeclaration bodyDeclaration) {
return CONSTRUCTORS_INDEX;
}
int flags = method.getModifiers();
if (Modifier.isStatic(flags))
if (Modifier.isStatic(flags)) {
return STATIC_METHODS_INDEX;
else
} else {
return METHOD_INDEX;
}
}
case ASTNode.FIELD_DECLARATION: {
if (JdtFlags.isStatic(bodyDeclaration))
if (JdtFlags.isStatic(bodyDeclaration)) {
return STATIC_FIELDS_INDEX;
else
} else {
return FIELDS_INDEX;
}
}
case ASTNode.INITIALIZER: {
int flags = bodyDeclaration.getModifiers();
if (Modifier.isStatic(flags))
if (Modifier.isStatic(flags)) {
return STATIC_INIT_INDEX;
else
} else {
return INIT_INDEX;
}
}
case ASTNode.TYPE_DECLARATION:
case ASTNode.ENUM_DECLARATION:
Expand Down Expand Up @@ -280,7 +283,7 @@ public int compare(BodyDeclaration bodyDeclaration1, BodyDeclaration bodyDeclara
int length2 = parameters2.size();

int len = Math.min(length1, length2);
for (int i = 0; i < len; i++) {
for (int i = 0;i < len;i++) {
SingleVariableDeclaration param1 = parameters1.get(i);
SingleVariableDeclaration param2 = parameters2.get(i);
cmp = buildSignature(param1.getType()).compareTo(buildSignature(param2.getType()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,21 @@ class JdtFlags {
static final int VISIBILITY_CODE_INVALID = -1;

static boolean isStatic(BodyDeclaration bodyDeclaration) {
if (isNestedInterfaceOrAnnotation(bodyDeclaration))
if (isNestedInterfaceOrAnnotation(bodyDeclaration)) {
return true;
}
int nodeType = bodyDeclaration.getNodeType();
if (nodeType != ASTNode.METHOD_DECLARATION
&& nodeType != ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION
&& isInterfaceOrAnnotationMember(bodyDeclaration))
&& isInterfaceOrAnnotationMember(bodyDeclaration)) {
return true;
if (bodyDeclaration instanceof EnumConstantDeclaration)
}
if (bodyDeclaration instanceof EnumConstantDeclaration) {
return true;
if (bodyDeclaration instanceof EnumDeclaration && bodyDeclaration.getParent() instanceof AbstractTypeDeclaration)
}
if (bodyDeclaration instanceof EnumDeclaration && bodyDeclaration.getParent() instanceof AbstractTypeDeclaration) {
return true;
}
return Modifier.isStatic(bodyDeclaration.getModifiers());
}

Expand All @@ -60,8 +64,9 @@ private static boolean isProtected(BodyDeclaration bodyDeclaration) {
}

private static boolean isPublic(BodyDeclaration bodyDeclaration) {
if (isInterfaceOrAnnotationMember(bodyDeclaration))
if (isInterfaceOrAnnotationMember(bodyDeclaration)) {
return true;
}
return Modifier.isPublic(bodyDeclaration.getModifiers());
}

Expand All @@ -80,14 +85,15 @@ private static boolean isNestedInterfaceOrAnnotation(BodyDeclaration bodyDeclara
}

static int getVisibilityCode(BodyDeclaration bodyDeclaration) {
if (isPublic(bodyDeclaration))
if (isPublic(bodyDeclaration)) {
return Modifier.PUBLIC;
else if (isProtected(bodyDeclaration))
} else if (isProtected(bodyDeclaration)) {
return Modifier.PROTECTED;
else if (isPackageVisible(bodyDeclaration))
} else if (isPackageVisible(bodyDeclaration)) {
return Modifier.NONE;
else if (isPrivate(bodyDeclaration))
} else if (isPrivate(bodyDeclaration)) {
return Modifier.PRIVATE;
}
Assert.isTrue(false);
return VISIBILITY_CODE_INVALID;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ public EclipseBasedStepBuilder(String formatterName, String formatterStepExt, Pr

/** Returns the FormatterStep (whose state will be calculated lazily). */
public FormatterStep build() {
var roundtrippableState = new EclipseStep(formatterVersion, formatterStepExt, FileSignature.promise(settingsFiles), JarState.promise(() -> {
return JarState.withoutTransitives(dependencies, jarProvisioner);
}));
var roundtrippableState = new EclipseStep(formatterVersion, formatterStepExt, FileSignature.promise(settingsFiles), JarState.promise(() -> JarState.withoutTransitives(dependencies, jarProvisioner)));
return FormatterStep.create(formatterName + formatterStepExt, roundtrippableState,
EclipseStep::state, stateToFormatter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public abstract class EquoBasedStepBuilder {
private File cacheDirectory;

/** Initialize valid default configuration, taking latest version */
public EquoBasedStepBuilder(
protected EquoBasedStepBuilder(
String formatterName,
Provisioner mavenProvisioner,
@Nullable String defaultVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,15 @@ public String endingFor(File file) {

static class RuntimeInit {
/** /etc/gitconfig (system-global), ~/.gitconfig (each might-not exist). */
final FileBasedConfig systemConfig, userConfig;
final FileBasedConfig systemConfig;
final FileBasedConfig userConfig;

/** Repository specific config, can be $GIT_COMMON_DIR/config, project/.git/config or .git/worktrees/<id>/config.worktree if enabled by extension */
final Config repoConfig;

/** Global .gitattributes file pointed at by systemConfig or userConfig, and the file in the repo. */
final @Nullable File globalAttributesFile, repoAttributesFile;
final @Nullable File globalAttributesFile;
final @Nullable File repoAttributesFile;

/** git worktree root, might not exist if we're not in a git repo. */
final @Nullable File workTree;
Expand Down Expand Up @@ -235,7 +237,7 @@ private Runtime atRuntime() {
}

/** https://github.com/git/git/blob/1fe8f2cf461179c41f64efbd1dc0a9fb3b7a0fb1/Documentation/gitattributes.txt */
static class Runtime {
static final class Runtime {
/** .git/info/attributes (and the worktree with that file) */
final List<AttributesRule> infoRules;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public boolean isClean(Project project, ObjectId treeSha, File file) throws IOEx
return isClean(project, treeSha, relativePath);
}

private Map<Repository, DirCache> dirCaches = new HashMap<>();
private final Map<Repository, DirCache> dirCaches = new HashMap<>();

/**
* This is the highest-level method, which all the others serve. Given the sha
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public final class EclipseCdtFormatterStep {
private EclipseCdtFormatterStep() {}

private static final String NAME = "eclipse cdt formatter";
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(17, "11.6");
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String>support(NAME).add(17, "11.6");

public static String defaultVersion() {
return JVM_SUPPORT.getRecommendedFormatterVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public final class GrEclipseFormatterStep {
private GrEclipseFormatterStep() {}

private static final String NAME = "eclipse groovy formatter";
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String> support(NAME).add(11, "4.26").add(17, "4.35");
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String>support(NAME).add(11, "4.26").add(17, "4.35");

public static String defaultVersion() {
return JVM_SUPPORT.getRecommendedFormatterVersion();
Expand Down Expand Up @@ -66,9 +66,8 @@ protected P2Model model(String version) {
"org.codehaus.groovy.eclipse.core",
"org.eclipse.jdt.groovy.core",
"org.codehaus.groovy"));
model.addFilterAndValidate("no-debug", filter -> {
filter.exclude("org.eclipse.jdt.debug");
});
model.addFilterAndValidate("no-debug", filter ->
filter.exclude("org.eclipse.jdt.debug"));
// work around https://github.com/groovy/groovy-eclipse/issues/1617
model.useMavenCentral = false;
return model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public String getFormatted(File file, String rawUnix) {
}
}

public static class Builder {
public static final class Builder {
private Builder() {}

private String runToFix;
Expand Down Expand Up @@ -161,7 +161,7 @@ public String getMessage() {
public static final int MAX_FILES_TO_LIST = 10;

private final StringBuilder buffer = new StringBuilder(MAX_CHECK_MESSAGE_LINES * 64);
private int numLines = 0;
private int numLines;

private final CleanProvider formatter;

Expand Down Expand Up @@ -203,7 +203,7 @@ private void addFile(String arg) {
if (!lines.isEmpty()) {
addIntendedLine(NORMAL_INDENT, lines.get(0));
}
for (int i = 1; i < Math.min(MIN_LINES_PER_FILE, lines.size()); ++i) {
for (int i = 1;i < Math.min(MIN_LINES_PER_FILE, lines.size());++i) {
addIntendedLine(DIFF_INDENT, lines.get(i));
}

Expand Down
Loading
Loading