Skip to content

fix: resolve static analysis issues in code #13270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

ungerts
Copy link
Contributor

@ungerts ungerts commented Jun 6, 2025

Description

This pull request addresses various static analysis warnings to improve overall code quality and maintainability. The changes include:

  • Using string format placeholders ({}) in log messages instead of string concatenation
  • Correcting keyword import ordering for consistency
  • Refining the use of generic types for better type safety
  • Optimizing lambda expressions for readability and performance
  • Applying consistent code style across the modified files

These are non-functional changes, purely aimed at cleanup and improvement.

Steps to test

No functional behavior has changed, so no specific testing steps are required. However, reviewers may:

  1. Run a full build and ensure all tests pass
  2. Open and use the modified parts of the application to confirm there are no regressions
  3. Use static analysis tools (e.g., CheckStyle, SpotBugs, IDE inspections) to confirm that previous warnings are now resolved

No UI changes have been made, so no screenshots are necessary.

Mandatory checks

  • I own the copyright of the code submitted and I license it under the MIT license
  • [/] Change in CHANGELOG.md described in a way that is understandable for the average user (if change is visible to the user)
  • [/] Tests created for changes (if applicable)
  • Manually tested changed features in running JabRef (always required)
  • [/] Screenshots added in PR description (if change is visible to the user)
  • Checked developer's documentation: Is the information available and up to date? If not, I outlined it in this pull request.
  • Checked documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request to the documentation repository.

Fix various static analysis warnings including
- Use string format placeholders in log messages
- Fix keyword import ordering
- Improve generic type usage
- Optimize lambda expressions
- Apply consistent code style

These changes improve code quality and maintainability without changing functionality.
@jabref-machine

This comment was marked as off-topic.

@jabref-machine
Copy link
Collaborator

Note that your PR will not be reviewed/accepted until you have gone through the mandatory checks in the description and marked each of them them exactly in the format of [x] (done), [ ] (not done yet) or [/] (not applicable).

@@ -136,7 +135,7 @@ private List<Node> createRowButtons(SortCriterionViewModel criterionViewModel) {
private void clearCriterionRow(int row) {
List<Node> criterionRow = sortCriterionList.getChildren().stream()
.filter(item -> GridPane.getRowIndex(item) == row)
.collect(Collectors.toList());
.toList();
Copy link
Member

Choose a reason for hiding this comment

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

These to list changes must be checked in context. .toList() is not a drop in replacement, as if I recall correctly, Collectors.toList creates a mutable list and .toList an immutable one. Or am I wrong? @Siedlerchr

Copy link
Member

Choose a reason for hiding this comment

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

Correct

Copy link
Member

@subhramit subhramit Jun 6, 2025

Choose a reason for hiding this comment

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

These changes are safe only if these are covered by tests, or it is manually ensured that the list is not being changed down the line

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

On a moderately-focused look I took last time, this instance was probably the only one that needed to be reverted.
There are about only 10 instances, so we can also revert them for safety and merge.

Copy link
Member

@subhramit subhramit Jun 18, 2025

Choose a reason for hiding this comment

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

Yep, checked the rest - should not cause issues. reverted this one.

subhramit
subhramit previously approved these changes Jun 18, 2025
Copy link
Member

@subhramit subhramit left a comment

Choose a reason for hiding this comment

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

Good to go from me

Edit: After a messy merge.

subhramit
subhramit previously approved these changes Jun 18, 2025
subhramit
subhramit previously approved these changes Jun 18, 2025
Copy link

trag-bot bot commented Jun 18, 2025

@trag-bot didn't find any issues in the code! ✅✨

@koppor koppor marked this pull request as ready for review June 24, 2025 10:27
@@ -194,11 +194,11 @@ private Optional<Path> askForSavePath() {
// Workaround for linux systems not adding file extension
if (!savePath.getFileName().toString().toLowerCase().endsWith(".bib")) {
savePath = Path.of(savePath.toString() + ".bib");
if (!Files.notExists(savePath)) {
if (!dialogService.showConfirmationDialogAndWait(Localization.lang("Overwrite file"), Localization.lang("'%0' exists. Overwrite file?", savePath.getFileName()))) {
if (!Files.notExists(savePath) && !dialogService.showConfirmationDialogAndWait(Localization.lang("Overwrite file"),
Copy link

Choose a reason for hiding this comment

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

Double negative 'notExists' makes the code harder to read and understand. Should use 'Files.exists()' instead for better readability and maintainability.

@subhramit subhramit added dev: code-quality Issues related to code or architecture decisions status: awaiting-second-review For non-trivial changes labels Jun 24, 2025
Comment on lines +310 to +311
Optional<Charset> newEncoding = dialogService.showChoiceDialogAndWait(Localization.lang("Save library"), Localization.lang("Select new encoding"),
Localization.lang("Save library"), encoding, Encodings.getCharsets());
Copy link
Member

Choose a reason for hiding this comment

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

Convention is to put every argument in a single line.

Comment on lines 18 to 23
private DirectoryStream.Filter<Path>[] filters;

@SafeVarargs
public ChainedFilters(DirectoryStream.Filter<Path>... filters) {
this.filters = filters;
}
Copy link
Member

Choose a reason for hiding this comment

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

SafeVarArgs annotation is like SuppressWarnings. But ignoring warnings is imho not the best idea.
Can we refactor this to use proper list and do sthg like this?

        for (DirectoryStream.Filter<Path> filter : filters) {
            this.filters.add(filter);
        }

Can we use List.of on this?
Can the method signature be refactored to use a List?

@@ -176,7 +176,7 @@ private void setupValidation() {
keywordRegexValidator = new FunctionBasedValidator<>(
keywordGroupSearchTermProperty,
input -> {
if (!keywordGroupRegexProperty.getValue()) {
if (Boolean.FALSE.equals(keywordGroupRegexProperty.getValue())) {
Copy link
Member

Choose a reason for hiding this comment

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

keywordGroupRegexProperty.getValue() looks like it is returning a boxed version of ObservableBooleanValue#get which returns a native boolean. Or am i missing something? Is it maybe better to use get() instead

grafik
grafik
grafik

Copy link
Member

Choose a reason for hiding this comment

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

Yeah something like a .getValue().get

Comment on lines +256 to +257
typeTexProperty.addListener((_, _, isSelected) -> {
if (Boolean.TRUE.equals(isSelected)) {
Copy link
Member

Choose a reason for hiding this comment

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

here the boxed version seems correct.

@@ -162,7 +162,7 @@ private FileNodeViewModel searchDirectory(Path directory) throws IOException {
try (Stream<Path> filesStream = Files.list(directory)) {
fileListPartition = filesStream.collect(Collectors.partitioningBy(path -> path.toFile().isDirectory()));
} catch (IOException e) {
LOGGER.error("%s while searching files: %s".formatted(e.getClass().getName(), e.getMessage()), e);
LOGGER.error("{} while searching files:", e.getClass().getName(), e);
Copy link
Member

Choose a reason for hiding this comment

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

Is the name of the error even neccessary? Wouldn't it suffice to just put "Error searching file." and let the logger handle the exception e?

sb.append(", data=").append(data);
sb.append('}');
return sb.toString();
String sb = "AbstractCitationKeyPattern{defaultPattern=" + defaultPattern + ", data=" + data + '}';
Copy link
Member

Choose a reason for hiding this comment

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

Maybe with java textblock and linebreaks easier to read?

Copy link
Member

Choose a reason for hiding this comment

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

This whole class is superfluous and can be removed imho.
ENCODINGS and ENCODINGS_DISPLAYNAMES are only used in tests, which can be removed too. Especially these. Not null and size not 0. Useless testing of standard jdk methods.
Im not even sure that distinct() is neccessary on available charsets. But that can either be inlined or moved to another class, maybe OS or sthg. Wdyt @Siedlerchr @koppor ?

@@ -447,8 +447,9 @@ public class JabRefCliPreferences implements CliPreferences {
*/
public JabRefCliPreferences() {
try {
if (Files.exists(Path.of("jabref.xml"))) {
importPreferences(Path.of("jabref.xml"));
Path preferebcesPath = Path.of("jabref.xml");
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Path preferebcesPath = Path.of("jabref.xml");
Path preferencesPath = Path.of("jabref.xml");

Comment on lines 168 to 172
case "." -> {
continue; // Stay in current directory
}
case ".." -> {
currentDirectory = currentDirectory.getParent();
continue;
// Stay in current directory
}
case ".." -> currentDirectory = currentDirectory.getParent();
case "*" -> { // for all direct subdirs
Copy link
Member

Choose a reason for hiding this comment

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

May be functionally correct, but I think it was more easily understandable before.
Now you have three cases with a statement block and one in the middle without.
Before you know, with continue, do nothing else, next dir, now you look for the end of the swith an look, if there is any code.

Comment on lines 32 to 46

// Regex
// (see http://www.doi.org/doi_handbook/2_Numbering.html)
private static final String DOI_EXP = ""
+ "(?:urn:)?" // optional urn
private static final String DOI_EXP = "(?:urn:)?" // optional urn
+ "(?:doi:)?" // optional doi
+ "(" // begin group \1
+ "10" // directory indicator
+ "(?:\\.[0-9]+)+" // registrant codes
+ "[/:%]" // divider
+ "(?:.+)" // suffix alphanumeric string
+ ")"; // end group \1
private static final String FIND_DOI_EXP = ""
+ "(?:urn:)?" // optional urn
private static final String FIND_DOI_EXP = "(?:urn:)?" // optional urn
+ "(?:doi:)?" // optional doi
+ "(" // begin group \1
+ "10" // directory indicator
Copy link
Member

Choose a reason for hiding this comment

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

Please adapt all the tabs to keep the comments in one column

@@ -91,7 +92,8 @@ FileNodeViewModel searchDirectory(Path directory, UnlinkedPDFFileFilter unlinked
// 2. GitIgnoreFilter
ChainedFilters filters = new ChainedFilters(unlinkedPDFFileFilter, new GitIgnoreFileFilter(directory));
Map<Boolean, List<Path>> directoryAndFilePartition;
try (Stream<Path> filesStream = StreamSupport.stream(Files.newDirectoryStream(directory, filters).spliterator(), false)) {
Copy link
Member

Choose a reason for hiding this comment

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

Why is it split in two ?

@@ -164,7 +164,7 @@ private void setupValidation() {
}

// Edit group, changed name to something that is already present
return (editedGroup == null) || editedGroup.getName().equals(name) || (groupsWithSameName <= 0);
return (editedGroup == null) || editedGroup.getName().equals(name) || (groupsWithSameName == 0);
Copy link
Member

Choose a reason for hiding this comment

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

This changes semantics!

@subhramit subhramit added status: changes-required Pull requests that are not yet complete and removed status: awaiting-second-review For non-trivial changes labels Jun 28, 2025
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: changes-required Pull requests that are not yet complete
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants