Skip to content

Add Contract annotation to nullaway-annotations#1569

Merged
msridhar merged 3 commits into
uber:masterfrom
codingkiddo:add-contract-annotation
May 15, 2026
Merged

Add Contract annotation to nullaway-annotations#1569
msridhar merged 3 commits into
uber:masterfrom
codingkiddo:add-contract-annotation

Conversation

@codingkiddo

@codingkiddo codingkiddo commented May 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #1543.

This PR adds com.uber.nullaway.annotations.Contract to the nullaway-annotations artifact.

NullAway already recognizes annotations whose simple name is Contract, so this provides a NullAway-owned annotation users can depend on directly.

Changes:

  • Add @Contract annotation under com.uber.nullaway.annotations
  • Use RetentionPolicy.CLASS
  • Support METHOD and CONSTRUCTOR targets
  • Add Javadoc for value() and pure()

Tested with:

  • ./gradlew :annotations:build
  • ./gradlew :annotations:javadoc
  • ./gradlew spotlessCheck

Summary by CodeRabbit

  • New Features
    • Added a new @Contract annotation for methods and constructors with a required contract string; it's documented and retained in compiled classes, with Javadoc describing the contract grammar and examples.
  • Tests
    • Added a test confirming the @Contract annotation is recognized and influences nullness reasoning at call sites.

Review Change Stack

@CLAassistant

CLAassistant commented May 8, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 211b6f0e-fe16-4047-8bad-bf7595d58c41

📥 Commits

Reviewing files that changed from the base of the PR and between 3fd1d2e and bdfca04.

📒 Files selected for processing (1)
  • nullaway/src/test/java/com/uber/nullaway/ContractsTests.java

Walkthrough

Adds a new annotation type com.uber.nullaway.annotations.Contract with @Documented, CLASS retention, and targets METHOD and CONSTRUCTOR. The annotation exposes a required String value() element for contract clauses and includes Javadoc describing the contract-string grammar and an example. Also adds a JUnit test nullAwayContractAnnotation that configures NullAway to recognize the annotation and verifies behavior at a call site invoking a method annotated with @Contract.

Possibly related PRs

  • uber/NullAway#1295: Adds and tests a com.uber.nullaway.annotations.Contract annotation and related contract handling.
  • uber/NullAway#1346: Extends ContractsTests usage of @com.uber.nullaway.annotations.Contract to exercise contract-based nullness behaviors.
  • uber/NullAway#1447: Adds contract-related tests and updates ContractHandler logic for interpreting contract clauses.

Suggested reviewers

  • msridhar
  • yuxincs
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a Contract annotation to the nullaway-annotations artifact.
Linked Issues check ✅ Passed The PR fulfills issue #1543 by adding an official @Contract annotation to the nullaway-annotations artifact with proper documentation and test coverage.
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the @Contract annotation and its test; no unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@msridhar msridhar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for this! I have a few comments on the annotation itself. Also, please add a unit test showing this annotation has the intended effect with NullAway

Comment thread annotations/src/main/java/com/uber/nullaway/annotations/Contract.java Outdated
Comment thread annotations/src/main/java/com/uber/nullaway/annotations/Contract.java Outdated
Comment thread annotations/src/main/java/com/uber/nullaway/annotations/Contract.java Outdated
@codecov

codecov Bot commented May 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.40%. Comparing base (9b04703) to head (bdfca04).

Additional details and impacted files
@@            Coverage Diff            @@
##             master    #1569   +/-   ##
=========================================
  Coverage     88.40%   88.40%           
  Complexity     2881     2881           
=========================================
  Files           103      103           
  Lines          9637     9637           
  Branches       1940     1940           
=========================================
  Hits           8520     8520           
  Misses          535      535           
  Partials        582      582           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@msridhar msridhar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Meant to request changes before

@msridhar

msridhar commented May 8, 2026

Copy link
Copy Markdown
Collaborator

Also @codingkiddo we need you to sign the CLA before we can accept this contribution

Signed-off-by: Vinod Kumar <codingkiddo@gmail.com>
@codingkiddo codingkiddo force-pushed the add-contract-annotation branch from a5efb4b to 3fd1d2e Compare May 9, 2026 08:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@annotations/src/main/java/com/uber/nullaway/annotations/Contract.java`:
- Around line 34-43: Update the Contract annotation so it's compatible with
common JetBrains-style usages by making the existing String value() optional
(give it a default, e.g., ""), and add a boolean pure() default false element;
modify the annotation declaration in Contract (the value() method and add
pure()) so usages like `@Contract`(pure = true) and `@Contract`("...") both compile
without changes to callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ff49900f-3ab3-4bb5-809f-ecbc4fd7e7c2

📥 Commits

Reviewing files that changed from the base of the PR and between a5efb4b and 3fd1d2e.

📒 Files selected for processing (2)
  • annotations/src/main/java/com/uber/nullaway/annotations/Contract.java
  • nullaway/src/test/java/com/uber/nullaway/ContractsTests.java

Comment on lines +34 to +43
public @interface Contract {

/**
* Contains the contract clauses describing relationships between call arguments and the returned
* value or exceptional behavior.
*
* @return the contract string
*/
String value();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make @Contract signature compatible with common JetBrains-style usages.

value() is currently mandatory and pure() is missing, so usages like @Contract(pure = true) won’t compile with this new annotation. That undermines the “drop-in NullAway-owned Contract” goal for existing users.

Suggested API adjustment
 public `@interface` Contract {
@@
-  String value();
+  String value() default "";
+
+  /**
+   * Whether the annotated method has no side effects.
+   *
+   * `@return` {`@code` true} if the method is pure
+   */
+  boolean pure() default false;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@annotations/src/main/java/com/uber/nullaway/annotations/Contract.java` around
lines 34 - 43, Update the Contract annotation so it's compatible with common
JetBrains-style usages by making the existing String value() optional (give it a
default, e.g., ""), and add a boolean pure() default false element; modify the
annotation declaration in Contract (the value() method and add pure()) so usages
like `@Contract`(pure = true) and `@Contract`("...") both compile without changes to
callers.

@codingkiddo

Copy link
Copy Markdown
Contributor Author

Thanks for the review.

Updated the PR to address the comments:

  • Removed pure() since NullAway does not use it
  • Removed the related pure() Javadoc
  • Updated the annotation Javadoc to mention that it is inspired by org.jetbrains.annotations.Contract
  • Added grammar-style documentation for the contract string, following the Spring @Contract style
  • Added a NullAway unit test showing com.uber.nullaway.annotations.Contract is recognized and affects nullability analysis

Tested with:

  • ./gradlew :annotations:build
  • ./gradlew :annotations:javadoc
  • ./gradlew :nullaway:test --tests "com.uber.nullaway.ContractsTests"
  • ./gradlew spotlessCheck

@codingkiddo

codingkiddo commented May 9, 2026

Copy link
Copy Markdown
Contributor Author

Also @codingkiddo we need you to sign the CLA before we can accept this contribution

Done, I have signed the CLA.

I also noticed the CLA check was tied to my commit author email, so I have updated the commit author/signoff to use my GitHub-linked email and force-pushed the branch.

Could you please recheck the CLA status when you get a chance? Thanks!

@codingkiddo codingkiddo closed this May 9, 2026
@codingkiddo codingkiddo reopened this May 9, 2026
@codingkiddo codingkiddo requested a review from msridhar May 9, 2026 08:09

@msridhar msridhar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM, thank you!

@msridhar msridhar enabled auto-merge (squash) May 15, 2026 21:43
@msridhar msridhar merged commit 070840c into uber:master May 15, 2026
14 checks passed
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.

Add @Contract to NullAway annotations

3 participants