Always record @Labels-annotated methods regardless of trivial-method filters#324
Always record @Labels-annotated methods regardless of trivial-method filters#324
Conversation
Agent-Logs-Url: https://github.com/getappmap/appmap-java/sessions/598cfeb7-c862-4cad-8a2b-776d6b11c993 Co-authored-by: kgilpin <86395+kgilpin@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR ensures methods explicitly annotated with @Labels are always considered for recording, even when they match the trivial-method heuristics (getters/setters/equals/hashCode, etc.), so developer intent is not silently overridden.
Changes:
- Update
ConfigCondition.doMatch()to bypassignoreMethod()when the behavior has a@Labelsannotation. - Add
ConfigCondition.hasLabelsAnnotation(CtBehavior)helper that detects@Labelsvia class-name string matching. - Add tests for labeled vs. unlabeled getters with respect to
hasLabelsAnnotation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| agent/src/main/java/com/appland/appmap/process/conditions/ConfigCondition.java | Skip trivial-method filtering when @Labels is present; add helper to detect the annotation. |
| agent/src/test/java/com/appland/appmap/process/conditions/ConfigConditionTest.java | Add unit tests validating hasLabelsAnnotation on getters. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| if (!AppMapBehavior.isRecordable(behavior) || ignoreMethod(behavior)) { | ||
| if (!AppMapBehavior.isRecordable(behavior) || (!hasLabelsAnnotation(behavior) && ignoreMethod(behavior))) { |
There was a problem hiding this comment.
The updated if condition is now >100 characters, which violates the repository's Checkstyle line-length rule (config/checkstyle/checkstyle.xml:44-47 sets max=100). Please wrap this condition across multiple lines (e.g., split the || / && parts) to keep it within the configured limit.
| if (!AppMapBehavior.isRecordable(behavior) || (!hasLabelsAnnotation(behavior) && ignoreMethod(behavior))) { | |
| if (!AppMapBehavior.isRecordable(behavior) | |
| || (!hasLabelsAnnotation(behavior) && ignoreMethod(behavior))) { |
| @Test | ||
| void testLabeledGetterHasLabelsAnnotation(ClassBuilder classBuilder) throws Exception { | ||
| MethodBuilder methodBuilder = classBuilder.beginMethod(); | ||
| methodBuilder.setName("getSomething") | ||
| .setBody("return Integer.valueOf(1);") | ||
| .setReturnType("java.lang.Integer") | ||
| .addAnnotation("com.appland.appmap.annotation.Labels") | ||
| .endMethod(); | ||
| assertTrue(ConfigCondition.hasLabelsAnnotation(methodBuilder.getBehavior())); | ||
| assertTrue(ConfigCondition.isGetter(methodBuilder.getBehavior())); | ||
| } | ||
|
|
||
| @Test | ||
| void testUnlabeledGetterHasNoLabelsAnnotation(ClassBuilder classBuilder) throws Exception { | ||
| MethodBuilder methodBuilder = classBuilder.beginMethod(); | ||
| methodBuilder.setName("getSomething") | ||
| .setBody("return Integer.valueOf(1);") | ||
| .setReturnType("java.lang.Integer") | ||
| .endMethod(); | ||
| assertFalse(ConfigCondition.hasLabelsAnnotation(methodBuilder.getBehavior())); | ||
| assertTrue(ConfigCondition.isGetter(methodBuilder.getBehavior())); | ||
| } |
There was a problem hiding this comment.
These new tests validate hasLabelsAnnotation, but they don't assert the actual behavior change in ConfigCondition.match() (that a trivial getter annotated with @Labels is no longer filtered out by ignoreMethod). Consider adding/adjusting tests to configure AppMapConfig.get().packages to include TestClass#getSomething, then assert new ConfigCondition().match(...) returns true for the labeled getter and false for the unlabeled getter; this will protect the intended contract without relying on the helper being package-visible.
| private static final String LABELS_CLASS = "com.appland.appmap.annotation.Labels"; | ||
|
|
||
| static boolean hasLabelsAnnotation(CtBehavior behavior) { | ||
| return behavior.hasAnnotation(LABELS_CLASS); | ||
| } | ||
|
|
There was a problem hiding this comment.
There is already code in CodeObject that looks for label annotiations. This code needs to either use that, or (more likely) it should be extracted to a common module.
|
Note that labels can also be configured via appmap.yml — I believe these should also cause recording normally skipped methods. Possibly also all the methods which are explicitly named in the config file, even if not given labels there. If the user explicitly adds a method to the config file, they definitely want it to be recorded and will be confused why it isn't. |
The trivial-method filter in
ConfigCondition(which drops getters, setters,equals,hashCode, etc.) ran unconditionally, silently suppressing methods that carried an explicit@Labelsannotation. A developer opt-in signal was being overridden by an automatic heuristic.Changes
ConfigCondition—doMatch()now skipsignoreMethod()when the behavior is annotated with@Labels. AddedhasLabelsAnnotation(CtBehavior)static helper that checks by class name string (consistent withCodeObject's existing approach to avoid shadowing/relocation issues).ConfigConditionTest— two new tests assertinghasLabelsAnnotationcorrectly identifies annotated vs. unannotated getters.Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
checkstyle.org/opt/hostedtoolcache/CodeQL/2.24.3/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.24.3/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.24.3/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-ec80e5ba4b87d1b1/dbs/java/working/files-to-index1033880596315573192.list --sourceArchiveDir=/tmp/codeql-scratch-ec80e5ba4b87d1b1/dbs/java/src --outputDir=/tmp/codeql-scratch-ec80e5ba4b87d1b1/dbs/java/trap/java(dns block)If you need me to access, download, or install something from one of these locations, you can either: