googleapis / googleapis/google-cloud-java
Align VaporReference and ConcreteReference Nullability name() Formatting
- Dominant language
- Java
- Stars
- 2.1k
- Forks
- 1.2k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 154
Description
## Issue Details
There is a behavioral inconsistency in how JSpecify `@Nullable` annotations are prepended to class names between `ConcreteReference` and `VaporReference` in the `gapic-generator-java` AST. This technical debt is captured in the code via // TODO(miraleung): Give this behavioral parity with ConcreteReference.
1. **`ConcreteReference.name()`** manually and dynamically prepends `@Nullable ` to the class name if `isNullable()` is true:
```java
if (isNullable()) {
sb.append("@Nullable");
sb.append(SPACE);
}
sb.append(simpleName());
```
2. **`VaporReference.name()`** does not include this check in its name formation. Instead, nullability prepending for `VaporReference` was implemented purely inside the writer phase in `JavaWriterVisitor.visit(VaporReference)`.
This inconsistency causes issues when reference names are dynamically constructed or compared (for example, when a `VaporReference` or `ConcreteReference` is nested as a generic parameter inside another reference, since the parent's `build()` method calls `r.name()` on its generics to build its own name string).
To unblock the initial JSpecify `@Nullable` PR, a temporary patch was applied to copy over the minimal behavior, but we need a clean, long-term alignment.
### Proposed Follow-up Work:
1. Add a dedicated golden test case capturing the behavior of nullable inner classes and generic types to ensure we prevent regressions.
2. Refactor `VaporReference` and `ConcreteReference` to use a consistent representation of nullability formatting in `name()`.
3. Investigate if we can simplify `ConcreteReference` by removing the manual string formatting inside the AST class entirely, centralizing the nullability formatting logic inside the `JavaWriterVisitor`.
---
## Environment
* **OS Type and Version:** Linux
* **Java Version and JDK Vendor:** Java 11+
* **Module:** `sdk-platform-java/gapic-generator-java`
---
## Dependencies
* `com.google.api:gapic-generator-java`
---
## Reproducer
The issue can be reproduced by comparing the string returned by `name()` for a nullable `VaporReference` vs a nullable `ConcreteReference`:
```java
// ConcreteReference name will contain "@Nullable"
ConcreteReference.builder()
.setClazz(String.class)
.setIsNullable(true)
.build()
.name(); // Returns "@Nullable String"
// VaporReference name will NOT contain "@Nullable"
VaporReference.builder()
.setName("MyClass")
.setPakkage("com.google")
.setIsNullable(true)
.build()
.name(); // Returns "MyClass"
```
This causes formatting differences when these references are nested inside collection types (e.g. `List<@Nullable String>` vs `List`).
Contributor guide
Research direction
Start with ConcreteReference.name(), VaporReference.name(), and JavaWriterVisitor.visit(VaporReference) in the gapic-generator-java module to trace where nullable formatting is applied. Add golden coverage for nullable inner classes and generic types, then verify that nested reference names are formatted consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- tooling
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100