Skip to content

Add an ExportedTypes RPC to enumerate a package's public API - #8360

Draft
jkschneider wants to merge 1 commit into
mainfrom
build-type-table-rpc
Draft

Add an ExportedTypes RPC to enumerate a package's public API#8360
jkschneider wants to merge 1 commit into
mainfrom
build-type-table-rpc

Conversation

@jkschneider

@jkschneider jkschneider commented Aug 1, 2026

Copy link
Copy Markdown
Member

What

Adds an ExportedTypes RPC method to each language engine (C#, JavaScript, Go, Python) that enumerates the public types a set of own artifacts (assemblies / package directories / module directories) export into OpenRewrite JavaType.

  • Public types the own artifacts define come back with complete bodies — members, methods, supertype, interfaces.
  • Types they only reference come back shallow (FQN only) for the caller to resolve.

This lets a caller read a dependency's public API without re-parsing its sources.

Artifact-scoped resolution

The enumeration is a function of the artifact alone — the referenced packages are never enumerated:

  • C# reads the .dll's TypeRef FQNs directly, so a reference into an assembly that wasn't loaded still comes back as a shallow FQN class-ref rather than Unknown (only the BCL is supplied, so primitives resolve).
  • Go resolves the module's own go.mod requires (in the module cache) to name cross-module references.
  • Python derives the ty environment from the artifact and resolves against the package's own declared dependencies.

How

The response streams and paginates:

  • The engine sends the FQNs the artifacts define first, so the caller can tell defined types from references before the first type arrives, then the types as a ref-deduplicated object stream (the same wire format getObject uses).
  • RpcReceiveQueue gains a streaming receiveList(before, onChange, sink) overload so a client never materializes the whole list.
  • Each response is returned in fixed-size (1000-item) slices across the client's repeated identical requests, so no single message carries a large result.

Per-module

Module Enumerator RPC
rewrite-core streaming RpcReceiveQueue.receiveList overload
rewrite-csharp AssemblyTypeEnumerator (Roslyn) ExportedTypes handler + CSharpRewriteRpc.exportedTypes
rewrite-javascript exportedTypes (TypeScript checker) handler + JavaScriptRewriteRpc.exportedTypes
rewrite-go ExportedTypes (go/types) handler + GoRewriteRpc.exportedTypes
rewrite-python handler (ty) PythonRewriteRpc.exportedTypes

Tests

  • Enumerator tests per engine (own types complete with methods; references shallow; module-boundary and per-OS/alias correctness for Go).
  • Handler pagination tests per engine (slices reassemble the single-shot response exactly; cache evicted after drain).
  • C# integration test round-trips Newtonsoft.Json over the wire.

@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Aug 1, 2026
@jkschneider
jkschneider force-pushed the build-type-table-rpc branch from 060ab46 to 2af7b8a Compare August 1, 2026 23:18
@jkschneider jkschneider changed the title Add a BuildTypeTable RPC for per-dependency type enumeration Add an ExportedTypes RPC to enumerate a package's public API Aug 1, 2026
@jkschneider
jkschneider marked this pull request as draft August 2, 2026 12:46
@jkschneider
jkschneider force-pushed the build-type-table-rpc branch from 2af7b8a to a9d84ee Compare August 2, 2026 13:32
Each language engine (C#, JavaScript, Go, Python) gains an `ExportedTypes`
RPC method that enumerates the public types a set of "own" artifacts
(assemblies / package directories / module directories) export into
OpenRewrite `JavaType`. Public types the own artifacts define come back with
complete bodies (members, methods, supertype, interfaces); types they only
reference come back shallow (FQN only) for the caller to resolve. This lets a
caller read a dependency's public API without re-parsing its sources.

The enumeration is scoped to the artifact. A referenced type is named from
the artifact's own metadata where possible — C# reads the `.dll`'s TypeRef
FQNs, so a reference into an unloaded assembly still comes back as a shallow
FQN class-ref rather than Unknown — otherwise from the dependency's own
declared dependencies (Go resolves the module's `go.mod` requires; Python
resolves the package's own environment). The referenced packages themselves
are never enumerated, so the result is a function of the artifact alone.

The response streams: the engine sends the FQNs the artifacts define first,
so the caller can tell defined types from references before the first type
arrives, then the types as a ref-deduplicated object stream (the same wire
format `getObject` uses). `RpcReceiveQueue` gains a streaming `receiveList`
overload so a client never materializes the whole list. Each response is
paginated in fixed-size slices across the client's repeated identical
requests, so no single message carries a large result.

- rewrite-core: streaming `RpcReceiveQueue.receiveList(before, onChange, sink)`.
- rewrite-csharp: `AssemblyTypeEnumerator` (Roslyn) + handler + client.
- rewrite-javascript: `exportedTypes` (TypeScript checker) + handler + client.
- rewrite-go: `ExportedTypes` (go/types) + handler + client.
- rewrite-python: handler (ty) + client.
@jkschneider
jkschneider force-pushed the build-type-table-rpc branch from a9d84ee to d879efe Compare August 2, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

1 participant