Skip to content

Commit

Permalink
@PackageRecipeTags annotation on package-info
Browse files Browse the repository at this point in the history
Adds a package level annotation for adding tags to recipes at the
package-level scope.

Signed-off-by: Jonathan Leitschuh <[email protected]>
  • Loading branch information
JLLeitschuh committed Jan 29, 2024
1 parent 9c715c7 commit 275dc68
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 3 deletions.
39 changes: 39 additions & 0 deletions rewrite-core/src/main/java/org/openrewrite/PackageRecipeTags.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite;

import org.openrewrite.config.RecipeDescriptor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* A package-level annotation that can be used to tag all {@link Recipe} within a given package and children
* packages with a given tag.
* <p>
* This annotation is useful for tagging all recipes within a package with a given tag, without having to
* add it manually to each overridden {@link Recipe#getTags()} method.
* <p>
* The tag will not be accessible via {@link Recipe#getTags()}, but will be accessible via {@link RecipeDescriptor#getTags()}
* when the {@link RecipeDescriptor} is created via {@link Recipe#getDescriptor()}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PACKAGE})
public @interface PackageRecipeTags {
String[] value() default {};
}
41 changes: 38 additions & 3 deletions rewrite-core/src/main/java/org/openrewrite/Recipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,45 @@ protected RecipeDescriptor createRecipeDescriptor() {
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
Set<String> allTags = new LinkedHashSet<>(getTags());
allTags.addAll(getTagsForPackageAndParent(getClass().getPackage()));

return new RecipeDescriptor(
getName(),
getDisplayName(),
getDescription(),
allTags,
getEstimatedEffortPerOccurrence(),
options,
recipeList1,
getDataTableDescriptors(),
getMaintainers(),
getContributors(),
getExamples(),
recipeSource
);
}

return new RecipeDescriptor(getName(), getDisplayName(), getDescription(), getTags(),
getEstimatedEffortPerOccurrence(), options, recipeList1, getDataTableDescriptors(),
getMaintainers(), getContributors(), getExamples(), recipeSource);
/**
* Finds all {@link PackageRecipeTags} annotations on the package of the given class and all parent packages.
*
* @return The set of tags found.
*/
private static Set<String> getTagsForPackageAndParent(@Nullable Package p) {
if (p == null) {
return Collections.emptySet();
}
Set<String> tags = new LinkedHashSet<>();
PackageRecipeTags packageTags = p.getAnnotation(PackageRecipeTags.class);
if (packageTags != null) {
tags.addAll(Arrays.asList(packageTags.value()));
}
int lastDot = p.getName().lastIndexOf('.');
if (lastDot > 0) {
String parentPackage = p.getName().substring(0, lastDot);
tags.addAll(getTagsForPackageAndParent(Package.getPackage(parentPackage)));
}
return tags;
}

private List<OptionDescriptor> getOptionDescriptors(Class<?> recipeClass) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.tags;

import org.junit.jupiter.api.Test;
import org.openrewrite.Recipe;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.tags.child.ChildRecipeWithNoTags;

import java.util.Collections;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;

public class PackageRecipeTagsAnnotationTest {

private static class RecipeWithNoTags extends Recipe {
@Override
public String getDisplayName() {
return "Recipe with no tags";
}

@Override
public String getDescription() {
return "It's tag-less!";
}

@Override
public Set<String> getTags() {
// Look ma, no tags! 🤣
return Collections.emptySet();
}
}

@Test
void testRecipeWithNoTags() {
RecipeWithNoTags recipe = new RecipeWithNoTags();
RecipeDescriptor descriptor = recipe.getDescriptor();
assertThat(descriptor.getTags())
.withFailMessage("Expected tag to be pulled from package-info.java")
.contains("What a fun tag!");
}

@Test
void testChildRecipeWithNoTags() {
ChildRecipeWithNoTags recipe = new ChildRecipeWithNoTags();
RecipeDescriptor descriptor = recipe.getDescriptor();
assertThat(descriptor.getTags())
.withFailMessage("Expected tag to be pulled from parent package-info.java")
.contains("What a fun tag!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.tags.child;

import org.openrewrite.Recipe;

public class ChildRecipeWithNoTags extends Recipe {

@Override
public String getDisplayName() {
return "Recipe with no tags";
}

@Override
public String getDescription() {
return "It's tag-less!";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package org.openrewrite.tags.child;

import io.micrometer.core.lang.NonNullApi;
21 changes: 21 additions & 0 deletions rewrite-core/src/test/java/org/openrewrite/tags/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@PackageRecipeTags({"What a fun tag!"})
@NonNullApi
package org.openrewrite.tags;

import org.openrewrite.PackageRecipeTags;
import org.openrewrite.internal.lang.NonNullApi;

0 comments on commit 275dc68

Please sign in to comment.