Skip to content

Conversation

@rpalcolea
Copy link
Member

New Rules Added

Task Container API Rules

  • USE_NAMED_INSTEAD_OF_GET_BY_NAME: Enforces lazy task lookup using tasks.named() instead of tasks.getByName()
  • USE_CONFIGURE_EACH_INSTEAD_OF_ALL: Enforces lazy task configuration using configureEach() instead of all()

Service Injection Rules

  • USE_INJECTED_OBJECT_FACTORY: Plugins should inject ObjectFactory via constructor instead of calling project.getObjects()
  • USE_INJECTED_PROVIDER_FACTORY: Plugins should inject ProviderFactory via constructor instead of calling project.getProviders()

Provider API Rules

  • PROVIDER_PROPERTIES: Task input/output properties should use Provider API types (Property, RegularFileProperty, DirectoryProperty, etc.)
  • ABSTRACT_GETTERS: Task property getters returning Provider API types should be abstract
  • EXTENSION_PROPERTIES_USE_PROVIDER_API: Extension properties should use Provider API types for lazy configuration
  • EXTENSION_ABSTRACT_GETTERS: Extension property getters returning Provider API types should be abstract

Project Reference Rule

  • PLUGINS_SHOULD_NOT_STORE_PROJECT_REFERENCES: Plugins should not store Project instances as fields (breaks configuration cache)

Refactoring

  • Created TypeConstants.java to consolidate 32+ duplicate constant declarations across 5 files
  • Added reusable predicate helpers: isProviderApiType(), callsMethodOn(), callsMethodOnAny()

rules.put("task project access", taskActionShouldNotAccessProject);
rules.put("task dependencies", taskActionShouldNotCallGetTaskDependencies);
rules.put("lazy task registration", LAZY_TASK_CREATION);
rules.put("use named instead of getByName", USE_NAMED_INSTEAD_OF_GET_BY_NAME);
Copy link
Member

Choose a reason for hiding this comment

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

🎉

*/
public static final ArchRule EXTENSION_PROPERTIES_USE_PROVIDER_API = ArchRuleDefinition.priority(Priority.MEDIUM)
.classes()
.that().haveSimpleNameEndingWith("Extension")
Copy link
Member

Choose a reason for hiding this comment

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

this seems kind of handwavy... maybe there is a way to find classes that are called as an arg to ExtensionsContainer.create?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking about that. Need to dig deeper but wondering if I can look at the plugin class that creates the extension and then find the extension code but that seems like crossing boundaries in an archrule from what I understand so far, I'll think more about this one

Copy link
Member Author

Choose a reason for hiding this comment

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

actually,

I think I'll use getAccessesToSelf and see if it is accessed from a plugin. I think that will add an extra level of certainty

Copy link
Member Author

Choose a reason for hiding this comment

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

94d68cf improves things a bit.

I don't think I can detect project.extensions.create("greeting", GreetingExtension::class.java) easily 🤔

* system and improves build performance.
*/
public static final ArchRule EXTENSION_PROPERTIES_USE_PROVIDER_API = ArchRuleDefinition.priority(Priority.MEDIUM)
.classes()
Copy link
Member

Choose a reason for hiding this comment

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

this condition should probably be more in the shape of "fields declared in classes that (logic) should use provider api" and then the same for methods()

Copy link
Member Author

Choose a reason for hiding this comment

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

addressed by 66252c2

*/
public static final ArchRule PLUGINS_SHOULD_NOT_STORE_PROJECT_REFERENCES = ArchRuleDefinition.priority(Priority.HIGH)
.classes()
.that().implement("org.gradle.api.Plugin")
Copy link
Member

Choose a reason for hiding this comment

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

this condition can be more like "fields declared in classes that implement plugin should not have type of Project"

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 9cd1673

@rpalcolea
Copy link
Member Author

This is ready for review again @OdysseusLives @wakingrufus

@rpalcolea rpalcolea merged commit d00443e into main Jan 7, 2026
9 checks passed
@rpalcolea rpalcolea deleted the more-gradle-rules branch January 7, 2026 17:33
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.

4 participants