Skip to content

Enable Java recipes for Python via ty LSP type attribution#6593

Merged
jkschneider merged 2 commits intomainfrom
jkschneider/python-java-recipes
Jan 26, 2026
Merged

Enable Java recipes for Python via ty LSP type attribution#6593
jkschneider merged 2 commits intomainfrom
jkschneider/python-java-recipes

Conversation

@jkschneider
Copy link
Copy Markdown
Member

Summary

This PR enables 7 Java building-block recipes to work on Python code by implementing proper type attribution via the ty type checker:

  • FindMethods - Find method usages by pattern
  • FindTypes - Find type references by name
  • ChangeMethodName - Rename a method
  • ChangeType - Change a given type to another
  • DeleteMethodArgument - Delete an argument from method invocations
  • ReorderMethodArguments - Reorder method arguments
  • ChangePackage - Rename package/module name

Key Implementation Details

Type Attribution via ty LSP

  • TyLspClient runs ty server as a long-lived subprocess
  • Communicates via LSP protocol over stdin/stdout
  • Provides hover-based type information that maps to JavaType.Method with full declaring type, parameter names, and parameter types

PythonTypeMapping Enhancements

  • Parses method signatures from ty hover responses (e.g., def split(sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str])
  • Handles declaring type resolution for builtins (str, list, dict) and module types
  • Falls back to placeholder parameter names when ty is unavailable

Python Import Recipes

  • AddImport - Add Python imports with proper formatting
  • RemoveImport - Remove unused Python imports
  • ChangeImport - Migrate imports between modules (e.g., collections.Mappingcollections.abc.Mapping)

Dependency Workspace

  • DependencyWorkspace.java manages cached virtual environments for type resolution
  • LRU cache with automatic cleanup prevents unbounded disk usage
  • Enables type attribution for external packages

Test plan

  • Integration tests for all 7 recipes using builtin types (str, list)
  • Tests validate both positive matches and negative cases (no match when type differs)
  • DeleteMethodArgument tests verify actual argument deletion
  • ReorderMethodArguments tests verify argument reordering without infinite loops

This change enables 7 Java building-block recipes to work on Python code:
- FindMethods
- FindTypes
- ChangeMethodName
- ChangeType
- DeleteMethodArgument
- ReorderMethodArguments
- ChangePackage (via recipes.csv entry)

Key changes:

1. Type attribution via ty LSP client
   - New TyLspClient that runs `ty server` as a long-lived subprocess
   - Communicates via LSP protocol over stdin/stdout
   - Provides hover-based type information for Python code

2. Enhanced PythonTypeMapping
   - Maps Python types to JavaType equivalents for MethodMatcher
   - Parses method signatures from ty hover responses to extract
     parameter names and types
   - Handles declaring type resolution for both builtins and modules

3. Python-specific import recipes
   - AddImport: Add Python imports with proper formatting
   - RemoveImport: Remove unused Python imports
   - ChangeImport: Migrate imports between modules

4. Dependency workspace support
   - DependencyWorkspace.java manages cached venvs for type resolution
   - LRU cache with automatic cleanup of evicted entries
   - Enables type attribution for external packages

5. Integration tests for all 7 recipes
   - Tests use builtin types (str, list) that work without dependencies
   - Validates both positive matches and negative cases

Technical notes:
- ty is required for full type attribution; without it, recipes fall back
  to placeholder parameter names
- Parameter names are parsed from ty hover responses like:
  `def split(sep: str | None = ..., maxsplit: SupportsIndex = ...) -> list[str]`
Remove debugging statements that were used during development:
- python_sender.py: Remove _DEBUG_SENDER flag and _debug() calls
- python_receiver.py: Remove logger.debug() in _visit_method_invocation
  and _receive_search_result
- receive_queue.py: Remove logger.debug() calls in receive() and
  _do_change()
@jkschneider jkschneider merged commit df8e507 into main Jan 26, 2026
2 checks passed
@jkschneider jkschneider deleted the jkschneider/python-java-recipes branch January 26, 2026 13:35
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Jan 26, 2026
timtebeek added a commit that referenced this pull request Apr 28, 2026
…7510)

These cross-ecosystem rows were inadvertently removed in #6991 when
recipes.csv was regenerated by `MavenRecipeMarketplaceGenerator`, which
overwrites the file from a pure classpath scan and does not preserve
the manually-added rows that advertise these Java recipes to the
JavaScript (#6485), Python (#6593), and C# (#6678) ecosystems.

Restores `ChangeMethodName`, `ChangePackage`, `ChangeType`,
`DeleteMethodArgument`, `ReorderMethodArguments`, `search.FindMethods`,
and `search.FindTypes` for each of those three ecosystems, derived from
the current Java rows so they stay in sync with the latest option and
data table metadata.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant