Skip to content

Fix Nullwarnings - C (Mark bst package as nonnull by default)#15663

Merged
koppor merged 14 commits into
mainfrom
bst-null-marked
May 4, 2026
Merged

Fix Nullwarnings - C (Mark bst package as nonnull by default)#15663
koppor merged 14 commits into
mainfrom
bst-null-marked

Conversation

@calixtus

@calixtus calixtus commented May 3, 2026

Copy link
Copy Markdown
Member

Related issues and pull requests

Followup to #14802

PR Description

See qodo comment

Steps to test

Run JabRef, see no more nullaway warnings for bst packages

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • [.] I added JUnit tests for changes (if applicable)
  • [.] I added screenshots in the PR description (if change is visible to the user)
  • [.] I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • [.] I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [.] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@calixtus calixtus added the dev: code-quality Issues related to code or architecture decisions label May 3, 2026
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

(Agentic_describe updated until commit b5906c5)

Mark bst package as nonnull by default and remove null handling

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Mark bst package as nonnull by default with @NullMarked annotation
• Remove null handling code, enforce non-null contracts throughout
• Replace null values with empty strings in string operations
• Improve null safety in BstVMContext and related classes
• Refactor test access methods and enhance code clarity
Diagram
flowchart LR
  A["@NullMarked Annotations"] --> B["Remove Null Checks"]
  B --> C["Empty String Defaults"]
  C --> D["Improved Type Safety"]
  E["BstVM API Changes"] --> F["getContext Method"]
  F --> D
Loading

Grey Divider

File Changes

1. jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java Null safety +46/-65

Add null safety annotations and remove null handling

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java


2. jablib/src/main/java/org/jabref/logic/bst/BstVM.java Null safety +13/-11

Add @NullMarked, refactor stack access API

jablib/src/main/java/org/jabref/logic/bst/BstVM.java


3. jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java Null safety +5/-1

Add null safety annotations to record

jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java


View more (10)
4. jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java Null safety +29/-25

Add @NullMarked, replace null with empty strings

jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java


5. jablib/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java Null safety +2/-0

Add @NullMarked annotation to class

jablib/src/main/java/org/jabref/logic/bst/util/BstCaseChanger.java


6. jablib/src/main/java/org/jabref/logic/bst/util/BstNameFormatter.java Null safety +2/-1

Add @NullMarked annotation to class

jablib/src/main/java/org/jabref/logic/bst/util/BstNameFormatter.java


7. jablib/src/main/java/org/jabref/logic/bst/util/BstPurifier.java Null safety +2/-1

Add @NullMarked annotation to class

jablib/src/main/java/org/jabref/logic/bst/util/BstPurifier.java


8. jablib/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java Null safety +2/-1

Add @NullMarked annotation to class

jablib/src/main/java/org/jabref/logic/bst/util/BstTextPrefixer.java


9. jablib/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java Null safety +5/-3

Add null safety annotations and null checks

jablib/src/main/java/org/jabref/logic/bst/util/BstWidthCalculator.java


10. jablib/src/main/java/org/jabref/logic/preview/BstPreviewLayout.java Null safety +12/-4

Add @NullMarked and null safety checks

jablib/src/main/java/org/jabref/logic/preview/BstPreviewLayout.java


11. jablib/src/test/java/org/jabref/logic/bst/BstFunctionsTest.java 🧪 Tests +116/-113

Update tests to use new getContext API

jablib/src/test/java/org/jabref/logic/bst/BstFunctionsTest.java


12. jablib/src/test/java/org/jabref/logic/bst/BstVMTest.java 🧪 Tests +14/-14

Update tests to use new getContext API

jablib/src/test/java/org/jabref/logic/bst/BstVMTest.java


13. jablib/src/test/java/org/jabref/logic/bst/BstVMVisitorTest.java 🧪 Tests +30/-31

Update tests to use new getContext API

jablib/src/test/java/org/jabref/logic/bst/BstVMVisitorTest.java


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. render bibDatabase nullability mismatch📘 Rule violation ≡ Correctness
Description
BstVM is now @NullMarked, but render(List, BibDatabase) still documents bibDatabase as
potentially null while its signature does not declare @Nullable. This misaligned null-safety
contract can lead to incorrect usage (passing null) and runtime failures when null is assumed
impossible downstream.
Code

jablib/src/main/java/org/jabref/logic/bst/BstVM.java[R65-68]

 /// @param bibEntries  list of entries to convert
 /// @param bibDatabase (may be null) the bibDatabase used for resolving strings / crossref
 /// @return list of references in plain text form
-    public String render(@NonNull Collection<BibEntry> bibEntries, BibDatabase bibDatabase) {
+    public String render(List<BibEntry> bibEntries, BibDatabase bibDatabase) {
Evidence
PR Compliance ID 48 requires null-safety contracts to be aligned (annotations/contract must match
behavior). In BstVM (now @NullMarked), the render method parameter bibDatabase is implicitly
non-null, yet the Javadoc explicitly states it may be null, creating a contract mismatch.

jablib/src/main/java/org/jabref/logic/bst/BstVM.java[63-75]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BstVM` is annotated `@NullMarked`, but `render(List<BibEntry>, BibDatabase)` still documents `bibDatabase` as “may be null” while the method signature does not declare it as `@Nullable`. This creates a mismatch between documented behavior and the nullness contract implied by `@NullMarked`.
## Issue Context
The compliance rule requires overrides/public APIs to have consistent nullability contracts. If `bibDatabase` is truly optional, it must be declared `@Nullable` and handled safely (e.g., using a default). If it is required, the Javadoc must be updated to remove the “may be null” claim and call sites must not pass null.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstVM.java[63-89]
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[53-60]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. empty$ rejects null🐞 Bug ≡ Correctness
Description
bstEmpty now throws when the operand is null, but missing entry fields are still represented as null
and pushed onto the stack, so common field empty$ usage can crash the VM. This contradicts
existing tests expecting missing fields to be treated as empty.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R398-406]

     Object o1 = stack.pop();
-        if (o1 == null) {
-            LOGGER.trace("null is empty");
-            stack.push(BstVM.TRUE);
-            return;
-        }
-
     if (!(o1 instanceof String s)) {
         throw new BstVMException("Operand does not match function empty$ (line %d)".formatted(ctx.start.getLine()));
     }
-        boolean result = s.trim().isEmpty();
+        boolean result = StringUtil.isBlank(s);
     LOGGER.trace("empty$({}) result: {}", s, result);
     stack.push(result ? BstVM.TRUE : BstVM.FALSE);
Evidence
Missing fields are initialized as null and then pushed onto the VM stack; empty$ now requires a
String and throws for null, while the test suite demonstrates the expected behavior is that a
missing field counts as empty.

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[394-406]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[151-160]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[198-207]
jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[24-27]
jablib/src/test/java/org/jabref/logic/bst/BstFunctionsTest.java[224-248]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`empty$` now throws for `null` operands, but the VM still uses `null` to represent missing fields and pushes those nulls onto the stack. This can crash typical `.bst` programs that do `field empty$`.
### Issue Context
- ENTRY fields are initialized to `null` and remain `null` when unresolved.
- `resolveIdentifier` pushes the field value (possibly `null`) onto the stack.
- Existing tests expect missing fields to be treated as empty.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[394-406]
- jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[151-160]
- jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[198-207]
### Suggested change
Restore prior behavior in `bstEmpty`: if operand is `null`, push `TRUE` and return (or otherwise coerce `null` to ""). Keep throwing only for non-null, non-String operands.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Concat NPE on null 🐞 Bug ☼ Reliability
Description
bstConcat removed the null-to-empty-string normalization and now logs
o1.getClass()/o2.getClass() inside the error path, which will throw NullPointerException if
either operand is null. Since missing fields are still pushed as null, concatenating optional fields
can crash.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R192-197]

     Object o2 = stack.pop();
     Object o1 = stack.pop();
-        if (o1 == null) {
-            o1 = "";
-        }
-        if (o2 == null) {
-            o2 = "";
-        }
-
     if (!((o1 instanceof String) && (o2 instanceof String))) {
         LOGGER.error("o1: {} ({})", o1, o1.getClass());
         LOGGER.error("o2: {} ({})", o2, o2.getClass());
Evidence
The visitor still pushes null field values onto the stack; bstConcat’s error logging dereferences
operands (getClass) even when they may be null, and the previous code that converted null to "" was
removed.

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[188-202]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[151-160]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[198-207]
jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[24-27]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`bstConcat` can throw `NullPointerException` when either operand is `null` because it logs `o1.getClass()`/`o2.getClass()` and no longer normalizes nulls. Missing fields are still represented as `null` and pushed onto the stack.
### Issue Context
BST programs commonly concatenate optional fields; the VM currently uses `null` to represent a missing field value.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[188-202]
### Suggested change
- Reintroduce null-to-empty-string normalization (e.g., treat null as "").
- Make logging null-safe (e.g., log `o1 == null ? "<null>" : o1.getClass()`), or avoid logging `getClass()` on potentially null references.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (3)
4. Equals NPE on null 🐞 Bug ☼ Reliability
Description
bstEquals now calls o1.equals(o2) without guarding against null, so comparing a missing field
(null) can crash the VM. Missing fields are still pushed as null from entry field resolution.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R148-152]

     Object o1 = stack.pop();
     Object o2 = stack.pop();
-        if ((o1 == null) ^ (o2 == null)) {
-            stack.push(BstVM.FALSE);
-            return;
-        }
-
-        if ((o1 == null) && (o2 == null)) {
-            stack.push(BstVM.TRUE);
-            return;
-        }
-
     stack.push(o1.equals(o2) ? BstVM.TRUE : BstVM.FALSE);
 }
Evidence
The VM still pushes null values for missing fields; removing the explicit null-handling in bstEquals
means o1.equals(o2) will throw if o1 is null.

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[142-152]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[151-160]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[198-207]
jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[24-27]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`bstEquals` can throw `NullPointerException` when either operand is `null` due to `o1.equals(o2)`. The VM still uses `null` to represent missing fields.
### Issue Context
Missing entry fields are inserted as `null` and pushed onto the stack during identifier resolution.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[142-152]
### Suggested change
Replace the comparison with `Objects.equals(o1, o2)` (or restore the prior explicit null-handling) to preserve expected semantics for null operands (null==null true, null==non-null false).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. STRINGS now stores empty📘 Rule violation ≡ Correctness
Description
visitStringsCommand now initializes declared strings to "" instead of null, but the existing
visitor test still asserts the values are null, likely causing test failures and/or unintended
behavior change. Tests should be updated to match the new contract or the behavior should be
reverted/adjusted with a clear rationale.
Code

jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[R46-48]

   for (BstParser.IdentifierContext identifierContext : ctx.ids.identifier()) {
-            bstVMContext.strings().put(identifierContext.getText(), null);
+            bstVMContext.strings().put(identifierContext.getText(), "");
   }
Evidence
PR Compliance ID 22 requires updating/adapting tests when behavior changes. The PR changes the
STRINGS command initialization from null to "", while the corresponding test still expects
null values for declared strings.

AGENTS.md
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[41-49]
jablib/src/test/java/org/jabref/logic/bst/BstVMVisitorTest.java[23-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`visitStringsCommand` now stores `""` for declared strings, but `BstVMVisitorTest.visitStringsCommand()` still asserts the values are `null`.
## Issue Context
This PR changes nullability semantics in the BST package; tests must be updated to reflect the intended contract (null vs empty string) for `STRINGS` variables.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[41-49]
- jablib/src/test/java/org/jabref/logic/bst/BstVMVisitorTest.java[23-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. cite$ may push nothing🐞 Bug ≡ Correctness
Description
BstCiteFunction.execute no longer pushes any value when an entry has no citation key, violating the
contract that cite$ “pushes” a string and breaking stack arity. This can cause downstream built-ins
to throw (stack underflow) or produce incorrect output.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R387-394]

+        public void execute(BstVMVisitor visitor, ParserRuleContext ctx, @Nullable BstEntry bstEntry) {
+            if (bstEntry == null) {
           execute(visitor, ctx);
           return;
       }
-            stack.push(bstEntryContext.entry.getCitationKey().orElse(null));
+            bstEntry.entry.getCitationKey().ifPresent(stack::push);
   }
Evidence
The new implementation uses ifPresent, so cite$ pushes zero stack items when the citation key is
absent. BibEntry explicitly documents that citation keys might not be present, so this is a
realistic runtime path.

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[378-395]
jablib/src/main/java/org/jabref/model/entry/BibEntry.java[375-398]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`cite$` currently pushes nothing if `BibEntry#getCitationKey()` is empty. The VM expects built-ins to have stable stack behavior; `cite$` should push exactly one value.
### Issue Context
`BibEntry` explicitly states the citation key might not be present. A missing key should still result in one pushed value (e.g., empty string), not zero pushes.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[378-395]
- jablib/src/main/java/org/jabref/model/entry/BibEntry.java[375-398]
### Suggested fix
- Change `cite$` to always push one string:
- `stack.push(bstEntry.entry.getCitationKey().orElse(""));`
- Optionally log a warning when the key is absent to aid debugging, but do not skip pushing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

7. orElse("") hides absence 📘 Rule violation ⚙ Maintainability
Description
New/updated code uses Optional.orElse("") to convert absence into an empty string (e.g., for
citationKey and preamble). This can mask missing values and is non-idiomatic per the
Optional-usage compliance rule unless the empty-string fallback is handled explicitly/justified.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R370-376]

+        public void execute(BstVMVisitor visitor, ParserRuleContext ctx, @Nullable BstEntry bstEntry) {
+            if (bstEntry == null) {
             execute(visitor, ctx);
             return;
         }
-            stack.push(bstEntryContext.entry.getCitationKey().orElse(null));
+            stack.push(bstEntry.entry.getCitationKey().orElse(""));
Evidence
PR Compliance ID 11 forbids introducing orElse("") patterns that turn missing Optional values into
empty strings without clear justification. The changed code pushes an empty string when
citationKey is absent and also defaults missing preamble to "" via orElse("").

AGENTS.md
jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[53-60]
jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[361-377]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The updated code uses `Optional.orElse("")` to substitute missing values with an empty string. This hides absence and violates the Optional idioms compliance rule unless the fallback is handled explicitly.
## Issue Context
If the BST VM semantics truly require the “null string” to be represented as `""`, handle the absence explicitly (e.g., `ifPresentOrElse(...)` with a clear comment/log), or model the value as an `Optional<String>` until the final push/assignment point.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[53-60]
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[361-377]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Preamble null database NPE🐞 Bug ≡ Correctness
Description
BstFunctions now uses Optional.of(bibDatabase) for preamble extraction, which throws if
bibDatabase is null, even though BstVM.render(..., bibDatabase) still documents that the
database may be null. Calling render(entries, null) will now crash during VM setup.
Code

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[R55-59]

     this.strings = bstVMContext.strings();
     this.integers = bstVMContext.integers();
     this.functions = bstVMContext.functions();
-        this.preamble = Optional.ofNullable(bstVMContext.bibDatabase()).flatMap(BibDatabase::getPreamble).orElse("");
+        this.preamble = Optional.of(bstVMContext.bibDatabase()).flatMap(BibDatabase::getPreamble).orElse("");
     this.stack = bstVMContext.stack();
Evidence
The constructor unconditionally wraps bstVMContext.bibDatabase() with Optional.of(...), while
the render API explicitly states the argument may be null; the two are inconsistent and produce an
NPE if the documented contract is used.

jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[53-60]
jablib/src/main/java/org/jabref/logic/bst/BstVM.java[63-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BstFunctions` assumes `bibDatabase` is non-null (`Optional.of(...)`), but `BstVM.render(..., bibDatabase)` is documented as allowing null. This mismatch creates an easy-to-hit NPE for callers following the documentation.
### Issue Context
Even if current in-repo call sites pass a non-null database, the public API contract still claims null is acceptable.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java[53-60]
- jablib/src/main/java/org/jabref/logic/bst/BstVM.java[63-75]
### Suggested change (choose one)
1) Preserve contract: switch back to `Optional.ofNullable(bstVMContext.bibDatabase())` and annotate the render parameter/context field as `@Nullable` as needed.
2) Tighten contract: update Javadoc to state `bibDatabase` must be non-null and add `Objects.requireNonNull(bibDatabase)` in `render(...)` (and keep `Optional.of(...)`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Trivial normalizeFieldValue comment📘 Rule violation ⚙ Maintainability
Description
The added comment /// Trims braces and resolve months restates what the helper does rather than
explaining rationale/constraints. This reduces signal-to-noise in documentation comments.
Code

jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[R98-99]

+    /// Trims braces and resolve months
+    private static String normalizeFieldValue(String content, FieldWriter fieldWriter, Field field) {
Evidence
PR Compliance ID 5 requires comments to explain "why" rather than repeating behavior. The new ///
comment is a simple paraphrase of the method’s implementation.

AGENTS.md
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[98-99]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The comment above `normalizeFieldValue(...)` is a "what" comment and does not add rationale.
## Issue Context
Project guideline prefers comments that explain intent/constraints rather than restating code.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[98-99]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
10. NullMarked vs null containers🐞 Bug ⚙ Maintainability
Description
@NullMarked is applied to BST classes/records while core containers are still designed to store
nulls (e.g., stack and entry field maps), but their generic types are not marked nullable. This
makes the nullness contract misleading and can cause future changes to introduce NPEs by trusting
non-null-by-default types.
Code

jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[R16-27]

+@NullMarked
public record BstVMContext(List<BstEntry> entries,
                      Map<String, String> strings,
                      Map<String, Integer> integers,
                      Map<String, BstFunctions.BstFunction> functions,
                      Deque<Object> stack,
-                           BibDatabase bibDatabase,
+                           @Nullable BibDatabase bibDatabase,
                      Optional<Path> path) {
-    public BstVMContext(List<BstEntry> entries, BibDatabase bibDatabase, Path path) {
+    public BstVMContext(List<BstEntry> entries, @Nullable BibDatabase bibDatabase, @Nullable Path path) {
   // LinkedList instead of ArrayDeque, because we (currently) need null support
   this(entries, new HashMap<>(), new HashMap<>(), new HashMap<>(), new LinkedList<>(), bibDatabase, Optional.ofNullable(path));
}
Evidence
BstVMContext is annotated @NullMarked but its Deque is explicitly created as a LinkedList because
null support is needed, implying stack elements may be null; similarly BstVMVisitor (also
@NullMarked) writes null values into entry maps. The current type signatures do not reflect that
nullable reality.

jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[16-27]
jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[152-180]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
BST code is now annotated with `@NullMarked`, but multiple containers still intentionally store null values (stack elements, entry fields/local strings). The generic types currently do not express this, so nullness tooling (and future readers) will assume non-null where null is valid.
### Issue Context
This PR’s goal is to reduce nullness warnings. To do that safely, nullability should be represented in the type system rather than relying on conventions.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/bst/BstVMContext.java[16-27]
- jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java[152-180]
### Suggested fix
- Update container types to reflect nullable elements/values where null is part of semantics, e.g.:
- `Deque<@Nullable Object>` for the stack (if null stack entries are valid),
- `Map<String, @Nullable String>` for maps that store null as “missing”.
- Then adjust local variables accordingly (e.g., `@Nullable String value = ...`) to prevent future unsafe dereferences under `@NullMarked`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread jablib/src/main/java/org/jabref/logic/bst/BstVMVisitor.java
Comment thread jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java
@calixtus calixtus marked this pull request as draft May 3, 2026 07:34
@calixtus calixtus marked this pull request as ready for review May 4, 2026 07:59
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit b5906c5

Comment thread jablib/src/main/java/org/jabref/logic/bst/BstVM.java
Comment thread jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java
Comment thread jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java
Comment thread jablib/src/main/java/org/jabref/logic/bst/BstFunctions.java
@calixtus calixtus added the status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers label May 4, 2026
koppor
koppor previously approved these changes May 4, 2026
@koppor koppor enabled auto-merge May 4, 2026 18:59
@koppor koppor added this pull request to the merge queue May 4, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label May 4, 2026
Merged via the queue into main with commit 3cdecb4 May 4, 2026
57 checks passed
@koppor koppor deleted the bst-null-marked branch May 4, 2026 20:10
Siedlerchr added a commit that referenced this pull request May 5, 2026
* upstream/main: (775 commits)
  Chore(deps): Bump com.konghq:unirest-modules-gson in /versions (#15682)
  Chore(deps): Bump org.glassfish.jaxb:jaxb-runtime in /versions (#15681)
  Update dependency com.konghq:unirest-modules-gson to v4.9.0 (#15679)
  Integrate with SearchRxiv  (#15373)
  Fix requirements (#15600)
  refactor: less objects during writing (#15677)
  Fix: suppress WARN for empty or blank column name in MainTableColumnModel#parse() (#15576)
  New Crowdin updates (#15676)
  Chore(deps): Bump com.github.ben-manes.caffeine:caffeine in /versions (#15673)
  Fix Nullwarnings - C (Mark bst package as nonnull by default) (#15663)
  Chore(deps): Bump com.github.javaparser:javaparser-symbol-solver-core (#15674)
  Chore(deps): Bump com.github.javaparser:javaparser-core in /versions (#15672)
  New Crowdin updates (#15669)
  Fix OpenRewrite (#15670)
  Udpate heylogs (and fix CHANGELOG.md) (#15671)
  Improve security and prevent shell injection for push2applications (#15628)
  Fix depdency analysis (#15668)
  Always use CI-local "gradle", instead of gradlew (#15667)
  Change OpenRewrite task to use rewriteDryRun (#15664)
  Add small documentation to parameter (#15666)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev: code-quality Issues related to code or architecture decisions status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants