Skip to content

Conversation

@rcosta358
Copy link
Collaborator

@rcosta358 rcosta358 commented Nov 15, 2025

This PR closes #82 and liquid-java/vscode-liquidjava#3, by making it possible for the verifier to report more than one error at a time. This was done by throwing an LJError which stops the verification until it is caught in the method, class, interface or field visitors in the RefinementTypeChecker and then resuming the verification. For the other visitor classes, a general try-catch is present in the RefinementProcessor.

Tests were also added.


Additional Improvement

The verifier sometimes caught the same error twice, because spoon was calling the visitor methods more than once. Claude fixed this by changing pkg.accept() to pkg.getTypes().forEach() in theRefinementProcessor, to prevent types (classes, methods, interfaces, fields) in nested packages from being verified multiple times when the ProcessingManager traversed the package hierarchy.

This change also makes the verification run faster.

Before

@Override
public void process(CtPackage pkg) {
if (!visitedPackages.contains(pkg)) {
visitedPackages.add(pkg);
Context c = Context.getInstance();
c.reinitializeAllContext();
pkg.accept(new FieldGhostsGeneration(c, factory)); // generate annotations for field ghosts
pkg.accept(new ExternalRefinementTypeChecker(c, factory));
pkg.accept(new MethodsFirstChecker(c, factory)); // double passing idea (instead of headers)
pkg.accept(new RefinementTypeChecker(c, factory));
}
}
}

After

@Override
public void process(CtPackage pkg) {
if (!visitedPackages.contains(pkg)) {
visitedPackages.add(pkg);
Context c = Context.getInstance();
c.reinitializeAllContext();
try {
// process types in this package only, not sub-packages
// first pass: gather refinements
pkg.getTypes().forEach(type -> {
type.accept(new FieldGhostsGeneration(c, factory)); // generate annotations for field ghosts
type.accept(new ExternalRefinementTypeChecker(c, factory)); // process external refinements
type.accept(new MethodsFirstChecker(c, factory)); // double passing idea (instead of headers)
});
// second pass: check refinements
pkg.getTypes().forEach(type -> {
type.accept(new RefinementTypeChecker(c, factory));
});
} catch (LJError e) {
diagnostics.add(e);
}
}
}
}

Errors thrown stopped package traversal, so we need to catch them earlier to continue processing files in the same package.
Wrap class annotation processing and child element visiting in separate try-catches so errors in one element don't prevent processing of sibling elements.
Changed from `pkg.accept()` to `pkg.getTypes().forEach()` in `RefinementProcessor` to prevent types in nested packages from being verified multiple times when `ProcessingManager` traverses the package hierarchy.
@rcosta358 rcosta358 self-assigned this Nov 15, 2025
@rcosta358 rcosta358 added enhancement New feature or request error messages labels Nov 15, 2025
@rcosta358 rcosta358 linked an issue Nov 15, 2025 that may be closed by this pull request
Copy link
Collaborator

@CatarinaGamboa CatarinaGamboa left a comment

Choose a reason for hiding this comment

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

Great improvement 🔥🔥🔥

@rcosta358 rcosta358 merged commit a05507f into main Nov 16, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request error messages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show errors in multiple files during the same verification pass

3 participants