Skip to content

TS-48007 Match includes and excludes against the class name in reports - #998

Merged
Stef2k16 merged 16 commits into
masterfrom
ts/48007_java_profiler_includes
Oct 27, 2026
Merged

Stef2k16 merged 16 commits into
masterfrom
ts/48007_java_profiler_includes

Conversation

@DreierF

@DreierF DreierF commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Addresses issue TS-48007

includes and excludes patterns no longer need a leading *. Previously, e.g. com.company.* instrumented the right classes but then dropped them from the report (testwise-coverage-report, the agent's own reports, convert), because the report matched the patterns against the class file's path instead of the class name.

Breaking: patterns only match the class name, no longer parts of the class file's path (e.g. *target.classes.*), and nested classes are written with $ (e.g. com.company.Outer$Inner), like JaCoCo does during instrumentation.

  • FilteringAnalyzer reads the class name from the class file header (about 0.7 µs per class vs. about 91 µs for a full analysis) and passes the JVM internal name to ClasspathWildcardIncludeFilter.

  • Separate commit: OpenAnalyzer, a copy of JaCoCo's Analyzer, is replaced by JaCoCo's Analyzer, so it no longer has to be kept in sync with every JaCoCo upgrade. Errors that JaCoCo raises itself (e.g. for a corrupt ZIP) are still reported with our message, which includes the cause and a hint.

  • The unused AgentConfiguration.getPredicate() in the Gradle plugin is deleted.

  • The tia-maven system tests and the sample app use patterns without a leading *.

  • Separate commit: with duplicates=FAIL, the error for a duplicate class showed the name of a lambda instead of its message (since v37.0.1).

  • Changes are tested adequately

  • Teamscale documentation updated in case of user-visible changes (Teamscale branch ts/48007_java_profiler_includes, to be merged once this is released)

  • CHANGELOG.md updated

  • Present new features in N&N

  • TGA Tutorial updated (not needed: uses the configuration wizard, which is unchanged)

  • TIA Tutorial updated (not needed: uses the Gradle plugin with tia.*)

Please respect the vote of the Teamscale bot or flag irrelevant findings as tolerated or false positives. If you feel that the Teamscale config needs adjustment, please state so in a comment and discuss this with your reviewer.

🤖 Generated with Claude Code

DreierF and others added 7 commits October 26, 2026 10:14
The report side matched the patterns against a name derived from the class
file's location, e.g. ".home.build.target.classes.com.company.Foo", so
com.company.* selected classes for instrumentation and then dropped them from
the report. FilteringAnalyzer now reads the class name from the class file
header, which only scans the constant pool and costs about 1 µs per class,
and matches it like JaCoCo does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OpenAnalyzer was a copy of JaCoCo's Analyzer that only made analyzeClass(byte[])
and analyzerError protected. Now that FilteringAnalyzer filters in the public
analyzeClass(byte[], String), it can extend JaCoCo's Analyzer directly, and
AnalyzerCache overrides the new analyzeIncludedClass instead. This removes the
need to keep the copy in sync with every JaCoCo update. Errors from JaCoCo's own
ZIP, GZIP and Pack200 handling now carry JaCoCo's message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All callers pass internal names (ClassReader, ExecutionData, ClassFileTransformer),
so the contract and tests no longer mention dotted names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
analyzeJar copied JaCoCo's ZIP handling only to skip a shell script in front of
executable JARs. It now hands the wrapped stream to JaCoCo's analyzeAll, which
calls back into our analyzeAll for every entry. This also picks up JaCoCo's
handling of the IllegalArgumentException that JDKs below 23 throw for
malformed ZIP entries (JDK-8321156), which the copy lacked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DreierF and others added 9 commits October 27, 2026 09:48
Since OpenAnalyzer is gone, errors raised by JaCoCo itself (e.g. a corrupt ZIP)
only said "Error while analyzing <location> with JaCoCo <version>." analyzeAll
now replaces them by our error, which includes the message of the cause and a
hint how to fix it. Our errors are passed on unchanged to the archives that
contain their location, so they are not wrapped once per nesting level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
analyzeClass already creates a ClassReader to read the class name for the
filter. analyzeIncludedClass now receives it, so AnalyzerCache no longer parses
the class header a second time. FilteringAnalyzer itself cannot reuse it,
because JaCoCo's analyzeClass only takes the bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
error { ... } passed the lambda to error(Any), so the message of the error for a
duplicate class with duplicates=FAIL was the lambda's name, e.g.
"JaCoCoBasedReportGenerator$EnhancedCoverageVisitor$$Lambda/0x...@c730e65".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The filter needs the class name, so every class file's header is read before
filtering, while the path-based filter never read excluded class files. A
corrupt class file therefore failed the whole analysis even if it was excluded.
Since its class name is unknown, it is now logged and skipped. Class files of
unsupported Java versions are still reported as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The help of --includes and --excludes still described the matching against the
class file's location, e.g. that ZIP contents are separated with @.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ASM rejects a class file of an unsupported Java version before its class name
is known, so such a class file was reported as an error even if it was
excluded, while the error recommends to exclude it. Its class name is now read
from a copy with a supported version, so that excluded ones are skipped.

FilteringAnalyzerTest now names the locations that were filtered incorrectly
and shares its ZIP helper with AnalyzerCacheTest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AnalyzerCache and ProbesCache were only tested with a filter that includes all
classes. ClasspathWildcardIncludeFilterTest is now parameterized, so that a
failure names the pattern and the class name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Stef2k16
Stef2k16 merged commit 369d73d into master Oct 27, 2026
3 of 4 checks passed
@Stef2k16
Stef2k16 deleted the ts/48007_java_profiler_includes branch October 27, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants