Skip to content

Fixes of some nullaway warnings#15792

Open
InAnYan wants to merge 16 commits into
JabRef:mainfrom
InAnYan:fix/nmark-1
Open

Fixes of some nullaway warnings#15792
InAnYan wants to merge 16 commits into
JabRef:mainfrom
InAnYan:fix/nmark-1

Conversation

@InAnYan
Copy link
Copy Markdown
Member

@InAnYan InAnYan commented May 20, 2026

Related issues and pull requests

Not related to any issue - a continuous process.

PR Description

Just fixing nullaway warnings. The simplest ones.

Ocasionally some code changes - using modern streams, or better string builder usage.

Steps to test

Ideally - run tests for each of the affected files. In reality, just run JabRef unit tests and see that the check is green.

AI usage

I used AI (Google Gemini, ChatGPT, Claude) to consult and dive more into Nullaway and null issues. None of the AI tools were used to generate or edit code, and all my changes are manual.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • 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

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Resolve NullAway warnings with nullable annotations and Optional refactoring

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add @Nullable annotations to resolve NullAway warnings across multiple files
• Refactor getFieldValue() to return Optional instead of nullable String
• Change getString() and getEntryById() methods to return Optional types
• Add @Contract annotations to StringUtil methods for null-safety contracts
• Remove constructor from ParsedEntryLink and simplify nullable field handling
• Update test assertions to work with Optional return types
Diagram
flowchart LR
  A["NullAway Warnings"] -->|Add @Nullable annotations| B["Exception, Comparator, AuthorList"]
  A -->|Refactor to Optional| C["getString, getEntryById, getFieldValue"]
  A -->|Add @Contract annotations| D["StringUtil methods"]
  A -->|Simplify nullable fields| E["ParsedEntryLink, GroupTreeNode"]
  B --> F["Null-safety compliance"]
  C --> F
  D --> F
  E --> F

Loading

File Changes

1. jablib/src/main/java/org/jabref/logic/JabRefException.java Null-safety +4/-3

Add nullable annotation to localizedMessage field

jablib/src/main/java/org/jabref/logic/JabRefException.java


2. jablib/src/main/java/org/jabref/logic/bibtex/comparator/EntryComparator.java Null-safety +4/-2

Mark next comparator field as nullable

jablib/src/main/java/org/jabref/logic/bibtex/comparator/EntryComparator.java


3. jablib/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java ✨ Enhancement +7/-10

Refactor getFieldValue to return Optional

jablib/src/main/java/org/jabref/logic/bibtex/comparator/FieldComparator.java


View more (14)
4. jablib/src/main/java/org/jabref/logic/citation/repository/MVStoreBibEntryRelationRepository.java 🐞 Bug fix +3/-0

Add null check for lastRun variable

jablib/src/main/java/org/jabref/logic/citation/repository/MVStoreBibEntryRelationRepository.java


5. jablib/src/main/java/org/jabref/logic/cleanup/FieldFormatterCleanup.java Null-safety +9/-4

Handle Optional field values explicitly

jablib/src/main/java/org/jabref/logic/cleanup/FieldFormatterCleanup.java


6. jablib/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java Null-safety +1/-0

Filter optional strings with flatMap

jablib/src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java


7. jablib/src/main/java/org/jabref/logic/importer/ParserResult.java Null-safety +2/-1

Mark file path field as nullable

jablib/src/main/java/org/jabref/logic/importer/ParserResult.java


8. jablib/src/main/java/org/jabref/logic/search/sqlbased/SqlBasedLibrarySearcher.java Null-safety +2/-0

Filter optional entries with flatMap

jablib/src/main/java/org/jabref/logic/search/sqlbased/SqlBasedLibrarySearcher.java


9. jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java Null-safety +6/-2

Add contract annotations and nullable parameters

jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java


10. jablib/src/main/java/org/jabref/model/database/BibDatabase.java ✨ Enhancement +4/-4

Return Optional from getString and getEntryById

jablib/src/main/java/org/jabref/model/database/BibDatabase.java


11. jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java Null-safety +1/-1

Mark path parameter as nullable

jablib/src/main/java/org/jabref/model/database/BibDatabaseContext.java


12. jablib/src/main/java/org/jabref/model/entry/AuthorList.java Null-safety +3/-1

Mark latexFreeAuthors field as nullable

jablib/src/main/java/org/jabref/model/entry/AuthorList.java


13. jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java ✨ Enhancement +8/-10

Simplify linkedEntry to nullable field

jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java


14. jablib/src/main/java/org/jabref/model/groups/GroupTreeNode.java Null-safety +1/-1

Replace null with empty list in setGroup call

jablib/src/main/java/org/jabref/model/groups/GroupTreeNode.java


15. jablib/src/main/java/org/jabref/model/metadata/MetaData.java Null-safety +1/-1

Mark aiLibraryId field as nullable

jablib/src/main/java/org/jabref/model/metadata/MetaData.java


16. jablib/src/test/java/org/jabref/model/database/BibDatabaseTest.java 🧪 Tests +3/-4

Update tests to use Optional assertions

jablib/src/test/java/org/jabref/model/database/BibDatabaseTest.java


17. jablib/src/test/java/org/jabref/model/entry/EntryLinkListTest.java 🧪 Tests +0/-7

Remove ParsedEntryLink constructor test

jablib/src/test/java/org/jabref/model/entry/EntryLinkListTest.java


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

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

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2)

Grey Divider


Action required

1. ParsedEntryLink stores null state 📘 Rule violation ☼ Reliability
Description
The change replaces an Optional<BibEntry> field with a @Nullable BibEntry field and assigns it
via orElse(null), reintroducing null state where Optional handling was already present. This
increases NPE risk and violates the Optional-idiom guidance.
Code

jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java[R12-34]

Evidence
PR Compliance ID 8 requires using Optional idioms instead of converting Optionals into nullable
values; the modified code stores linkedEntry as @Nullable and explicitly assigns
database.getEntryByCitationKey(...).orElse(null) (and repeats this in setKey).

AGENTS.md: Use Optional idioms instead of nulls and avoid anti-pattern Optional.orElse(unusedValue)
jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java[12-34]

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

## Issue description
`ParsedEntryLink` was changed to store `linkedEntry` as a nullable field and uses `orElse(null)`, which reintroduces nulls instead of using Optional idioms.

## Issue Context
The compliance checklist requires preferring Optional operations over converting Optionals to nullable values.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java[12-34]

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


2. Invalid StringBuilder.repeat call 🐞 Bug ≡ Correctness
Description
StringUtil.alignStringTable now calls sb.repeat(" ", padding) where sb is a java.lang.StringBuilder;
there is no StringBuilder method overload that accepts (String,int), so this change will not
compile. This breaks any codepath that builds the aligned string table (and likely fails the build).
Code

jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[731]

Evidence
The PR branch code declares sb as a StringBuilder and then invokes sb.repeat(" ", padding),
which requires a repeat(String,int) instance method on StringBuilder and therefore cannot
compile as written.

jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[719-736]

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

### Issue description
`alignStringTable` constructs a `StringBuilder sb = new StringBuilder()` and then calls `sb.repeat(" ", padding)`. `StringBuilder` does not provide a `repeat(String, int)` method, so this is a compile-time error.

### Issue Context
This line replaced a working padding implementation (`sb.append(" ".repeat(padding))`).

### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[719-736]

### Suggested fix
Replace `sb.repeat(" ", padding);` with one of:
- `sb.append(" ".repeat(padding));` (closest to original)
- or a small loop appending spaces if preferred.

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



Remediation recommended

3. cleanupSingleField uses isEmpty+get 📘 Rule violation ⚙ Maintainability
Description
The modified code checks oldValue.isEmpty() and then calls oldValue.get() multiple times, which
is the Optional anti-pattern the checklist forbids and can reintroduce null-like control flow. This
reduces readability and makes future edits more error-prone.
Code

jablib/src/main/java/org/jabref/logic/cleanup/FieldFormatterCleanup.java[R60-71]

Evidence
PR Compliance ID 34 forbids isPresent()/isEmpty() followed by get() in the same control flow;
the updated cleanupSingleField introduces exactly that pattern (oldValue.isEmpty() then
oldValue.get() used multiple times).

jablib/src/main/java/org/jabref/logic/cleanup/FieldFormatterCleanup.java[60-81]
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
`cleanupSingleField` uses `Optional.isEmpty()` followed by `Optional.get()`, which violates the project's Optional control-flow requirement.

## Issue Context
The checklist requires using idiomatic Optional APIs (`map`, `orElse`, `ifPresent`, `orElseThrow`, etc.) instead of presence checks followed by `get()`.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/cleanup/FieldFormatterCleanup.java[60-81]

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


Grey Divider

Qodo Logo

Comment on lines +12 to 34
private final BibDatabase database;

private String key;
private Optional<BibEntry> linkedEntry;
private BibDatabase database;
@Nullable private BibEntry linkedEntry;

public ParsedEntryLink(String key, BibDatabase database) {
this.key = key;
this.linkedEntry = database.getEntryByCitationKey(this.key);
this.linkedEntry = database.getEntryByCitationKey(this.key).orElse(null);
this.database = database;
}

public ParsedEntryLink(BibEntry bibEntry) {
this.key = bibEntry.getCitationKey().orElse("");
this.linkedEntry = Optional.of(bibEntry);
}

public String getKey() {
return key;
}

public Optional<BibEntry> getLinkedEntry() {
return linkedEntry;
return Optional.ofNullable(linkedEntry);
}

public void setKey(String newKey) {
this.key = newKey;
this.linkedEntry = getDatabase().getEntryByCitationKey(this.key);
this.linkedEntry = getDatabase().getEntryByCitationKey(this.key).orElse(null);
}
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.

Action required

1. parsedentrylink stores null state 📘 Rule violation ☼ Reliability

The change replaces an Optional<BibEntry> field with a @Nullable BibEntry field and assigns it
via orElse(null), reintroducing null state where Optional handling was already present. This
increases NPE risk and violates the Optional-idiom guidance.
Agent Prompt
## Issue description
`ParsedEntryLink` was changed to store `linkedEntry` as a nullable field and uses `orElse(null)`, which reintroduces nulls instead of using Optional idioms.

## Issue Context
The compliance checklist requires preferring Optional operations over converting Optionals to nullable values.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/model/entry/ParsedEntryLink.java[12-34]

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No, according to big-heads it’s wrong to store optional as fields, and it should be used as a return type only

sb.append(pair.getKey());

sb.append(" ".repeat(padding));
sb.repeat(" ", padding);
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.

Action required

2. Invalid stringbuilder.repeat call 🐞 Bug ≡ Correctness

StringUtil.alignStringTable now calls sb.repeat(" ", padding) where sb is a java.lang.StringBuilder;
there is no StringBuilder method overload that accepts (String,int), so this change will not
compile. This breaks any codepath that builds the aligned string table (and likely fails the build).
Agent Prompt
### Issue description
`alignStringTable` constructs a `StringBuilder sb = new StringBuilder()` and then calls `sb.repeat(" ", padding)`. `StringBuilder` does not provide a `repeat(String, int)` method, so this is a compile-time error.

### Issue Context
This line replaced a working padding implementation (`sb.append(" ".repeat(padding))`).

### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/util/strings/StringUtil.java[719-736]

### Suggested fix
Replace `sb.repeat(" ", padding);` with one of:
- `sb.append(" ".repeat(padding));` (closest to original)
- or a small loop appending spaces if preferred.

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

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is

@InAnYan
Copy link
Copy Markdown
Member Author

InAnYan commented May 21, 2026

I don't understand why architecture test is failing. I used only jspecify nullable.

I can't use jetbrains @Contract? If not, this is sad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant