-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Add support for loading .blg warnings in Integrity Check Dialog #12866
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
Conversation
…d path resolution
public DialogService getDialogService() { | ||
return dialogService; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new public method 'getDialogService' returns 'null' if 'dialogService' is not initialized. It should return an Optional to avoid potential NullPointerExceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified to pass DialogService
from the constructor parameter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do DI by constructor. Getters for singletons are a no go.
*/ | ||
private void loadBibLogSettingsPane() { | ||
try { | ||
FXMLLoader loader = new FXMLLoader(getClass().getResource("BibLogSettingsPane.fxml")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calixtus Don't we use the afterburner fx stuff here?
/** | ||
* | ||
*/ | ||
public class BibWarning { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(quick initial comment)
Can this be a record? 😅
(and no empty JavaDoc please)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I've converted it to a record and removed the empty JavaDoc
*/ | ||
private Optional<BibWarning> parseWarningLine(String line) { | ||
// TODO: Support additional warning formats | ||
Pattern compile = Pattern.compile("^Warning--([a-zA-Z ]+) in ([^\\s]+)$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this into private static final
. - and use named groups 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated as suggested 👍
|
||
@FXML | ||
private void onBrowse() { | ||
FileChooser fileChooser = new FileChooser(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use jabref's dialogService for this: dialogService.showFileOpenDialog(fileDialogConfiguration).ifPresent(path -> ...)
and with FileDialogConfiguration offers the Builder pattern.
(see e.g NewLibraryFromPdfAction)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, already updated as suggested
return blgFilePath; | ||
} | ||
|
||
public void setBlgFilePath(Path path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method uses Objects.requireNonNull to check for null, which should be replaced with @nonnull annotation as per the guidelines.
|
||
List<IntegrityMessage> messages = BibWarningToIntegrityMessageConverter.convert(warnings, context); | ||
|
||
assertEquals(1, messages.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assertion statements should not include the message parameter. The method name should already convey the expected behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trag-bot This is wrong
src/main/java/org/jabref/gui/integrity/BibLogSettingsViewModel.java
Outdated
Show resolved
Hide resolved
metaData.getBlgFilePaths().forEach((user, path) -> { | ||
stringyMetaData.put(MetaData.BLG_FILE_PATH + "-" + user, Collections.singletonList(path.toString().trim())); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of .blg file paths serialization in org.jabref.logic.exporter.MetaDataSerializer requires corresponding test updates to ensure the new functionality is covered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
already covered this change in the test method serializeUserSpecificBlgPath()
・ࡇ・
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this -
do? Path, naming separator?
Maybe this could be a constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, the other meta data fields do it, too.
I am OK without constant - follow-up can refactor the whole MetaDataParser
^^
@@ -60,6 +61,9 @@ public static Map<String, String> getSerializedStringMap(MetaData metaData, | |||
.put(MetaData.FILE_DIRECTORY_LATEX + '-' + user, Collections.singletonList(path.toString().trim()))); | |||
metaData.getVersionDBStructure().ifPresent( | |||
versionDBStructure -> stringyMetaData.put(MetaData.VERSION_DB_STRUCT, Collections.singletonList(versionDBStructure.trim()))); | |||
metaData.getBlgFilePaths().forEach((user, path) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of serializing .blg file paths requires corresponding tests to be updated or added to ensure the new functionality is correctly implemented and verified.
|
||
import javafx.fxml.FXML; | ||
import javafx.scene.control.TextField; | ||
import javafx.stage.FileChooser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement for FileChooser is unnecessary as the dialogService is used for file dialogs, which aligns with the project's architecture guidelines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, the comment of trag bot is correct.
Tried out now with a MWE generated by https://github.com/latextemplates/generator-latex-template. Works. |
Thanks @koppor I noticed some of the checks are failing, I’ll take a look and try pushing a fix over this week. Let me know if there’s anything else I should work on :) |
src/main/java/org/jabref/gui/integrity/BibLogSettingsViewModel.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jabref/gui/integrity/BibLogSettingsViewModel.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
@Test | ||
void returnsDefaultBlgPathWhenUserPathIsAbsent() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test method names are descriptive enough, so using @DisplayName is unnecessary. The method name should be comprehensive enough to describe the test case.
} | ||
|
||
@Test | ||
void returnsEmptyWhenNoUserPathAndNoBibPath() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test method names are descriptive enough, so using @DisplayName is unnecessary. The method name should be comprehensive enough to describe the test case.
* Ensures that the trailing semicolon (used as separator in .bib metadata) is handled and stripped properly. | ||
*/ | ||
@Test | ||
void parsesUserSpecificBlgPathSuccessfully() throws Exception { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method name 'parsesUserSpecificBlgPathSuccessfully' is not comprehensive enough. It should describe the test case more clearly without needing a @DisplayName annotation.
private Runnable onBlgPathChanged; | ||
|
||
public void initializeViewModel(BibDatabaseContext context, Runnable onBlgPathChanged) throws JabRefException { | ||
if (context == null || context.getMetaData() == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it necessary to check for null
s here?
|
||
public Path getInitialDirectory() { | ||
return bibPath.flatMap(path -> Optional.ofNullable(path.getParent())) | ||
.orElse(Path.of(System.getProperty("user.home"))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this cross-platform ("user.home"
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not on Windows XP, but this is acceptable: https://stackoverflow.com/q/585534/873282
I only meant to leave a single comment here, but I think I accidentally triggered a full review by clicking the wrong button 😅 Also, I noticed that the Trag review has been marked as “in progress” for two days now, not sure if that’s expected or if something got stuck? |
It sometimes does that - pushing another commit refreshes it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some small comments towards a really JabRef-high-quality code 😅
/** | ||
* 1. Connects MetaData with the view. | ||
* 2. Wraps .blg warnings as IntegrityMessages. | ||
* 3. Supports file browsing and reset actions. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either html or Markdown - I propose markdown
/** | |
* 1. Connects MetaData with the view. | |
* 2. Wraps .blg warnings as IntegrityMessages. | |
* 3. Supports file browsing and reset actions. | |
*/ | |
/// 1. Connects MetaData with the view. | |
/// 2. Wraps .blg warnings as IntegrityMessages. | |
/// 3. Supports file browsing and reset actions. |
this.path.set(resolvedPath.toString()); | ||
if (metaData.getBlgFilePath(user).isEmpty()) { | ||
metaData.setBlgFilePath(user, resolvedPath); | ||
this.lastResolvedBlgPath = Optional.of(resolvedPath); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indent seems to be off
/** | ||
* Resolves custom or default .blg path for this library. | ||
* | ||
* Priority: | ||
* 1. User-defined path from MetaData | ||
* 2. Default: same name as .bib file with .blg extension | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** | |
* Resolves custom or default .blg path for this library. | |
* | |
* Priority: | |
* 1. User-defined path from MetaData | |
* 2. Default: same name as .bib file with .blg extension | |
*/ | |
/// Resolves custom or default .blg path for this library. | |
/// | |
/// Priority: | |
/// | |
/// 1. User-defined path from MetaData | |
/// 2. Default: same name as .bib file with .blg extension |
/** | ||
* Converts {@link BibWarning}s into {@link IntegrityMessage}s for integration with the existing integrity check UI. | ||
* | ||
* Notes: | ||
* - The current IntegrityMessage interface expects a {@link BibEntry} and a {@link Field}, | ||
* but .blg warnings come from a different source and may not include a field. | ||
* - For now, we map missing fields to a placeholder (InternalField.KEY_FIELD) to make it compatible with the UI. | ||
* - This is a minimal MVP solution to reuse the Integrity tab without changing the UI structure. | ||
* | ||
* Future direction: | ||
* - Consider defining a proper interface (e.g., IntegrityMessageWithField / WithoutField) | ||
* to support warnings without fields cleanly. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also convert to Markdown (to have the notes list rendered properly)
metaData.getBlgFilePaths().forEach((user, path) -> { | ||
stringyMetaData.put(MetaData.BLG_FILE_PATH + "-" + user, Collections.singletonList(path.toString().trim())); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, the other meta data fields do it, too.
I am OK without constant - follow-up can refactor the whole MetaDataParser
^^
assertEquals(2, messages.size()); | ||
|
||
IntegrityMessage msg1 = messages.getFirst(); | ||
assertEquals("empty journal", msg1.message()); | ||
assertEquals(firstEntry, msg1.entry()); | ||
assertEquals("journal", msg1.field().getName()); | ||
|
||
IntegrityMessage msg2 = messages.get(1); | ||
assertEquals("empty year", msg2.message()); | ||
assertEquals(secondEntry, msg2.entry()); | ||
assertEquals("year", msg2.field().getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to compare two lists directly? Or are IntegrityMessage
objects not good with equals?
BibLogPathResolver.resolve(metaData, bibPath, user) | ||
.ifPresent(resolvedPath -> { | ||
this.path.set(resolvedPath.toString()); | ||
if (metaData.getBlgFilePath(user).isEmpty()) { | ||
metaData.setBlgFilePath(user, resolvedPath); | ||
this.lastResolvedBlgPath = Optional.of(resolvedPath); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code does not follow the fail-fast principle. It should return early if the condition is not met, instead of nesting logic inside an if statement.
public void resetBlgFilePath() { | ||
metaData.clearBlgFilePath(user); | ||
userManuallySelectedBlgFile = false; | ||
Optional<Path> resolved = BibLogPathResolver.resolve(metaData, bibPath, user); | ||
if (resolved.isEmpty()) { | ||
path.set(""); | ||
lastResolvedBlgPath = Optional.empty(); | ||
return; | ||
} | ||
|
||
Path resolvedPath = resolved.get(); | ||
path.set(resolvedPath.toString()); | ||
lastResolvedBlgPath = Optional.of(resolvedPath); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method does not follow the fail-fast principle. It should return early if the condition is not met, instead of nesting logic inside an if statement.
if (context.getDatabase().getEntryByCitationKey(bibWarning.entryKey()).isEmpty()) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code should follow the fail fast principle by immediately handling invalid states and returning early instead of nesting logic inside else branches. This code should return early if the entry is not found.
new IntegrityMessage("empty year", secondEntry, FieldFactory.parseField("year")) | ||
); | ||
|
||
assertEquals(expectedMessages, actualMessages); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test uses assertEquals to compare lists of objects. It's better to assert the contents of objects directly to ensure more precise validation of the test results.
@wanling0000 One last thing: submodules |
@trag-bot didn't find any issues in the code! ✅✨ |
Fixed, thanks for the reminder! |
@wanling0000 good work! |
Closes #11998
This PR adds support for: Check integrity: Support for BibTeX .blg files
Users can now:
.blg
file from the same folder as the.bib
file;.blg
file via Browse and load BibTeX warnings;.blg
path;.blg
warnings when switching files (i.e., only show current.blg
file's messages);.blg
file path inMetaData
(saved along with.bib
file).Change Overview
BibWarning
.blg
warningMetaData.get/set/clearBlgFilePath()
.blg
file pathBibtexLogParser
.blg
lines intoBibWarning
objectsBibWarningToIntegrityMessageConverter
IntegrityMessage
BibLogPathResolver
.blg
file path: user-defined or fallbackMetaDataParser
BLG_FILE_PATH
in.bib
metadataMetaDataSerializer
BibLogSettingsViewModel
BibLogSettingsPane.fxml
BibLogSettingsPane.java
IntegrityCheckDialog.java
.blg
warnings and refresh table displayIntegrityCheckAction.java
.blg
warnings during initial dialog showScreenshots
❓Limitations of .blg Parsing – I would appreciate feedback
Right now, the .blg parser in this PR (BibtexLogParser) only supports a very simple warning format:
But I found that in real .blg files, there are other kinds of warnings that don’t follow this format.
For example, in this GitHub issue: James-Yu/LaTeX-Workshop#2324
This kind of warning does not point to a specific entry or field, so currently it is ignored by the parser.
I’m wondering:
Would it make sense to introduce an interface like IntegrityMessage, or is it better to wait and see more .blg formats before making this change?
At the moment I don’t have many .blg test files, so I’m not sure how common these “fieldless” warnings are.
If you have any suggestions on how to investigate this, I’d be happy to look into it!
Any feedback or thoughts on this would be really helpful, thank you!
Mandatory checks
CHANGELOG.md
described in a way that is understandable for the average user (if change is visible to the user)