Skip to content

refactor: move the SemanticDB to binary name conversion onto Symbol - #8763

Open
damiankus-vl wants to merge 3 commits into
scalameta:main-v2from
damiankus-vl:improvement-extract-common-symbol-conversion-operations
Open

refactor: move the SemanticDB to binary name conversion onto Symbol#8763
damiankus-vl wants to merge 3 commits into
scalameta:main-v2from
damiankus-vl:improvement-extract-common-symbol-conversion-operations

Conversation

@damiankus-vl

@damiankus-vl damiankus-vl commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

There are a few places where we convert SemanticDB symbols to Java binary names, for example

sym.stripSuffix("#").stripSuffix(".").replace('/', '.')

We could extract that logic to make it reusable

This change originated in from #8742
I've moved it to a separate PR to make the original one smaller

Summary by CodeRabbit

  • Bug Fixes

    • Improved Javadoc link resolution for nested Java classes and their members.
    • Fully qualified and same-package references now navigate more reliably to the correct source files.
    • Improved class name handling for source navigation, Java module lookup, and related tooling.
  • Tests

    • Added coverage for nested-class links, tooltips, resolution targets, and navigation to Java source files.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dc169c2a-9735-4909-8800-07a4782f1f28

📥 Commits

Reviewing files that changed from the base of the PR and between 2939548 and daced54.

📒 Files selected for processing (6)
  • metals/src/main/scala/scala/meta/internal/metals/mbt/VirtualTextDocument.scala
  • metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/ClasspathDefinitionIndex.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/Symbol.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/SymbolIndexBucket.scala
  • tests/unit/src/test/scala/tests/DocumentLinkLspSuite.scala
🚧 Files skipped from review as they are similar to previous changes (6)
  • mtags/src/main/scala/scala/meta/internal/mtags/SymbolIndexBucket.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/ClasspathDefinitionIndex.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/Symbol.scala
  • metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala
  • tests/unit/src/test/scala/tests/DocumentLinkLspSuite.scala
  • metals/src/main/scala/scala/meta/internal/metals/mbt/VirtualTextDocument.scala

📝 Walkthrough

Walkthrough

The change centralizes top-level SemanticDB symbol name conversion. Document links now resolve nested Javadoc classes. Classpath, source indexing, and virtual text document lookups use the shared conversions. Integration tests cover same-package and fully qualified nested classes.

Changes

Top-level symbol name conversion

Layer / File(s) Summary
Top-level symbol conversion helpers
mtags/src/main/scala/scala/meta/internal/mtags/Symbol.scala
Symbol now converts top-level symbols to binary and class names and reconstructs symbols from class names.
Document and virtual-text symbol resolution
metals/src/main/scala/scala/meta/internal/metals/mbt/VirtualTextDocument.scala, metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala, tests/unit/src/test/scala/tests/DocumentLinkLspSuite.scala
Virtual text uses shared class-name conversion. Javadoc resolution generates package-aware nested-class candidates. Tests cover same-package and fully qualified nested links.
Classpath and source index lookup
mtags/src/main/scala/scala/meta/internal/mtags/ClasspathDefinitionIndex.scala, mtags/src/main/scala/scala/meta/internal/mtags/SymbolIndexBucket.scala
Classfile paths, source paths, and Java reflective class names use the shared symbol conversions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Javadoc
  participant DocumentLinksProvider
  participant Symbol
  participant JavaSource
  Javadoc->>DocumentLinksProvider: submit nested class reference
  DocumentLinksProvider->>Symbol: construct candidate symbols
  DocumentLinksProvider->>JavaSource: resolve candidate
  JavaSource-->>DocumentLinksProvider: return Outer.java target
Loading

Possibly related PRs

  • scalameta/metals#8590: Related Java and nested-class symbol indexing changes in SymbolIndexBucket.scala.

Suggested reviewers: tgodzik

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The changes refactor symbol name conversion and do not address the linked issue's requirement to use a non-constant SymbolKind for val declarations [#39]. Update SymbolKind handling for val declarations, or link the issue that defines the Symbol name conversion refactor.
Out of Scope Changes check ⚠️ Warning The code changes concern SemanticDB symbol-to-binary-name conversion, which is unrelated to the linked issue about SymbolKind for val declarations [#39]. Move the symbol conversion refactor to a correctly scoped issue or add changes that address the linked SymbolKind requirement.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main refactor: moving SemanticDB-to-binary-name conversion logic onto Symbol.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala`:
- Line 299: Update classRefToSymbols so dotted Javadoc class references support
SemanticDB nested-class symbols: retain the Symbol.fromToplevelClassName
candidate for top-level classes, and additionally resolve nested segments using
the nested symbol form (for example, java/util/Map#Entry#). Return both
candidates when necessary so valid nested links can be found without breaking
top-level resolution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2f70fbcf-2869-436a-bb20-39d9c0d9e3fd

📥 Commits

Reviewing files that changed from the base of the PR and between d70c1d7 and 2e4557b.

📒 Files selected for processing (5)
  • metals/src/main/scala/scala/meta/internal/metals/mbt/VirtualTextDocument.scala
  • metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/ClasspathDefinitionIndex.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/Symbol.scala
  • mtags/src/main/scala/scala/meta/internal/mtags/SymbolIndexBucket.scala

Comment thread metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala`:
- Line 304: Update the dotted-reference handling around
DocumentLinksProvider.dottedClassRefToSymbols so references beginning with a
type name also generate the current-package candidate (for example,
a/Outer#Inner#) before unqualified candidates. Preserve existing resolution
behavior and add LSP regressions covering {`@link` Outer.Inner} and {`@link`
Outer.Inner#doSomething} in the same package.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ceb44c7-058d-499a-a63e-ebb52ec41fc5

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4557b and 80a0940.

📒 Files selected for processing (3)
  • metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala
  • tests/unit/src/test/scala/tests/DocumentLinkLspSuite.scala
  • tests/unit/src/test/scala/tests/parsing/DocumentLinksProviderSuite.scala

Comment thread metals/src/main/scala/scala/meta/internal/parsing/DocumentLinksProvider.scala Outdated
@damiankus-vl
damiankus-vl force-pushed the improvement-extract-common-symbol-conversion-operations branch from 80a0940 to dcc391a Compare August 4, 2026 07:47
damiankus-vl and others added 3 commits August 6, 2026 13:15
Five call sites spelled the same conversion out by hand: strip the descriptor
suffix off a toplevel symbol to get the name the JVM uses, and sometimes swap
`/` for `.` on top of that, or the other way around to build the symbol of a
class named the way `Class.forName` names it. Two of them wrote the two
stripSuffix calls in the opposite order, which reads like it might matter.

Symbol.toplevelBinaryName, Symbol.toplevelClassName and
Symbol.fromToplevelClassName state it once, the last one being the inverse of
the second. The scaladoc records why they answer for the toplevel class: a
nested class is Outer$Inner in a binary name but Outer#Inner# in a symbol, and
no caller needs that mapping.

MetalsPasteProvider and MunitTestFinder strip the same characters for different
reasons - one keeps the result in symbol form, the other must not walk up to
the toplevel class - so they stay as they are.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Javadoc separates a nested class from its outer one with a dot, the same
character that separates packages, so `java.util.Map.Entry` was read as class
Entry in package java.util.Map and looked up as `java/util/Map/Entry#`. No such
symbol exists - SemanticDB writes `java/util/Map#Entry#` - so the link resolved
to nothing, and so did every member reference through it.

Read the reference as a nested class first, splitting packages from types where
Java's naming convention says they part, and keep the all-packages reading as
the fallback for names that ignore the convention. The candidates already feed
a first-one-that-resolves lookup, so an extra one costs nothing when the first
answers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A nested class of the file's own package is written without any package at all,
so `Outer.Inner` is dotted while naming no package of its own. Both dotted
readings then miss: `Outer#Inner#` and `Outer/Inner#` describe a class in the
default package, and the same-package candidate that a simple name gets was
only built in the no-dots branch.

A reference that starts with a type now gets the current package prefixed onto
the readings, tried before the unqualified ones, so `Outer.Inner` inside
`package a` is looked up as `a/Outer#Inner#` first. The unqualified candidates
stay where they were, behind it, so nothing that resolved before stops.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@damiankus-vl
damiankus-vl force-pushed the improvement-extract-common-symbol-conversion-operations branch from dcc391a to daced54 Compare August 6, 2026 11:33
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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.

1 participant