Skip to content

feature: navigate to Java files materialized from .proto files#8699

Open
damiankus-vl wants to merge 3 commits into
scalameta:main-v2from
damiankus-vl:improve-protobuf-support
Open

feature: navigate to Java files materialized from .proto files#8699
damiankus-vl wants to merge 3 commits into
scalameta:main-v2from
damiankus-vl:improve-protobuf-support

Conversation

@damiankus-vl

Copy link
Copy Markdown
Contributor

Generate read-only Javas file from .proto files and materialize them under .metals/readonly, so go-to-definition on a proto-generated class (message, enum, gRPC stub) lands in the generated Java source alongside the .proto declaration. Route the materialized file to the proto's build target and feed the outlines through the turbine classpath so hover and completion resolve proto-generated types too.

DEMO

An example based on issue #8651 - https://github.com/buildfarm/buildfarm

  • go to persistentworkers/examples/src/test/java/adder/AdderTest.java
  • hover over waitAndRead in line 44
  • check the return type in the tooltip
  • go to the definition of waitAndRead
  • go to the definition of the return type (WorkResponse)

Before

The return value of waitAndRead is treated as Object
The definition of WorkResponse points to the .proto file
https://github.com/user-attachments/assets/386ddd4f-db38-40dd-8505-c3904d62612d

After

The return value of waitAndRead if a WorkResponse
The definition of WorkResponse points to both the .proto file and the generated Java file
https://github.com/user-attachments/assets/0853b964-c20b-4af9-a803-925dc6ff012f

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8cf2b341-72df-4973-8ee0-7d2afa33c977

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ 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.

@damiankus-vl
damiankus-vl force-pushed the improve-protobuf-support branch 2 times, most recently from b427446 to 6732291 Compare July 21, 2026 07:11
@odisseus
odisseus self-requested a review July 21, 2026 11:04

@tgodzik tgodzik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks pretty great! An I can confirm it works. I have some overall suggestions, nothing blocking.

* - `getFoo(+1).` -> `getFoo().`
* - `setBar(+3).` -> `setBar().`
*/
private def stripDisambiguators(symbol: String): String =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need this? Shouldn't we find the correct definition anyway?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

originally, stripDisambiguators was needed because there was no way to tell apart symbols related to overloaded methods (I think I've come across some case where a generated outline had two setters with the same names but different argument types)

I've added some logic to find the exact overload used by the caller based on the argument names and types, so we no longer need stripDisambiguators
f422d7a

@tgodzik tgodzik Jul 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the method order correspond to +1,+2 etc. We shouldn't need parameters:

Disambiguator is:

Concatenation of a left parenthesis ((), a tag and a right parenthesis ()). If the definition is not overloaded, the tag is empty. Two definitions are overloaded if they have the same name and both require a disambiguator. If the definition is overloaded, the tag is computed from the order of appearance of overloads in the source code (see "Function declarations and definitions" below for an example):
Empty string for the definition that appears first.
+1 for the definition that appears second.
+2 for the definition that appears third.

from https://scalameta.org/docs/semanticdb/specification#symbol-1

Comment thread tests/unit/src/test/scala/tests/mbt/ProtoGeneratedJavaFilesSuite.scala Outdated
Comment thread tests/unit/src/test/scala/tests/mbt/ProtoGeneratedJavaFilesSuite.scala Outdated
Comment thread tests/unit/src/test/scala/tests/mbt/ProtoGeneratedJavaFilesSuite.scala Outdated
Comment thread tests/unit/src/test/scala/tests/p/ProtoPCJavaSuite.scala Outdated
@tgodzik

tgodzik commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Also, looks like this fixes #8653 could you add a rename test as well?

Synthesize a Java outline from each .proto and materialize it as a read-only
file under .metals/readonly, so go-to-definition on a proto-generated class
(message, enum, gRPC stub) lands in the generated Java source alongside the
.proto declaration. Route the materialized file to the proto's build target
and feed the outlines through the turbine classpath so hover and completion
resolve proto-generated types too. Works for every build tool with no build
output and no configuration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@damiankus-vl
damiankus-vl force-pushed the improve-protobuf-support branch from 6732291 to c4562c0 Compare July 24, 2026 08:56
damiankus-vl and others added 2 commits July 24, 2026 13:50
The SemanticDB overload disambiguator carries no signature info and is
computed independently at the call site (mtags-java) and when
re-indexing the materialized outline (mtags), so it can disagree and
the previous fix had to return every name-matching candidate instead
of the one the user actually navigated to.

Thread the call site's real resolved parameter names/types
(MtagsIndexer.ParameterSignature) end-to-end through
mtags-interfaces/mtags-shared/mtags-java into metals' DefinitionResult,
and use them in DefinitionProviderProtobufSupport.findRange to narrow
multiple name-matching candidates down to the one whose signature
actually matches, comparing by dotted type-name suffix (the outline
refers to sibling types by simple name, the call site always resolves
fully qualified). Falls back to returning every name match, unchanged,
whenever the new info is unavailable or ambiguous.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The parser only recognized `syntax = "proto2"/"proto3";` at the top of a
.proto file, so any file using Protobuf Editions (`edition = "2023";`)
threw a ProtoError and failed to generate a Java outline entirely,
breaking Java-file navigation for those files.
@damiankus-vl
damiankus-vl force-pushed the improve-protobuf-support branch from c4562c0 to 2925ada Compare July 24, 2026 11:51
@damiankus-vl

Copy link
Copy Markdown
Contributor Author

Also, looks like this fixes #8653 could you add a rename test as well?

addressed in a separate PR
#8730

syntax = Optional.of(parseSyntax());
syntax = Optional.of(parseSyntax("syntax"));
break;
case "edition":

@damiankus-vl damiankus-vl Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

in the Bazel project there's a proto file that uses the edition keyword
https://github.com/bazelbuild/bazel/blob/master/src/main/protobuf/execution_graph_writer.proto

It breaks Metals with the following error

	2026-07-24 10:46:57.230 [info] 2026.07.24 10:46:57 WARN  Failed to generate Java outline for proto /Users/dkus/Documents/Projects/bazel/src/main/protobuf/execution_graph_writer.proto
scala.meta.internal.proto.diag.ProtoError: file:///Users/dkus/Documents/Projects/bazel/src/main/protobuf/execution_graph_writer.proto:15:1: Unexpected token: edition
	at scala.meta.internal.proto.parse.Parser.error(Parser.java:886)
	at scala.meta.internal.proto.parse.Parser.parseFile(Parser.java:92)
	at scala.meta.internal.proto.parse.Parser.parse(Parser.java:36)

Commit 2925ada should fix that

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.

3 participants