rewrite-python: Unknown declaring-type for unattributed method calls + public SearchResult.found#7631
Merged
jkschneider merged 1 commit intomainfrom May 10, 2026
Merged
Conversation
…+ public SearchResult.found
Two paired changes that together unblock ``Preconditions.check(uses_method(...), V())``
gates from failing wire-side evaluation when Python sources lack
receiver-type attribution (e.g. unit-test fixtures that don't import
the receiver).
## type_mapping
``PythonTypeMapping._get_declaring_type`` previously returned ``None``
when Ty couldn't resolve the receiver and AST inference didn't yield
a recognizable type. That left ``JavaType.Method._declaring_type`` as
``None`` for method invocations like ``my_array.tostring()`` in
unattributed sources. Java's ``MethodMatcher.matches`` accepts
``JavaType.Unknown`` receivers under wildcard patterns (``*..*``)
but rejects method types whose declaring type is null at the
``TypesInUse.hasMethodUse`` lookup level.
Now ``_get_declaring_type`` returns a non-null ``FullyQualified`` in
every case — falling back to the shared ``_UNKNOWN`` singleton — so
``HasMethod`` / ``UsesMethod`` precondition gates work against
unattributed code. The function signature changes from
``Optional[JavaType.FullyQualified]`` to ``JavaType.FullyQualified``
to document the new invariant. Resolution paths that previously
returned None now fall through to the AST-inference and Unknown
fallbacks.
## SearchResult.found
Adds a public ``SearchResult.found(tree, description=None)`` static
factory mirroring Java's ``org.openrewrite.marker.SearchResult.found``.
Returns a new tree carrying a fresh ``SearchResult`` marker — the
canonical "different tree" sentinel that ``Check`` /
``CompositePrecondition`` interpret as the gate matching. The native
``rewrite/python/search/{IsSourceFile,UsesType,UsesMethod}`` visitors
now call this instead of constructing the Markers/Marker pair by hand.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Preconditions.check(uses_method(...), V())gates from failing wire-side evaluation when Python sources lack receiver-type attribution (e.g. unit-test fixtures that don't import the receiver). The motivating regression: rewrite-migrate-python#54's recipe wraps were silently no-op'ing for inputs likemy_array.tostring()once the wire-sideHasMethodgate became active.type_mapping
PythonTypeMapping._get_declaring_typepreviously returnedNonewhen Ty couldn't resolve the receiver and AST inference didn't yield a recognizable type. That leftJavaType.Method._declaring_typeasNonefor method invocations likemy_array.tostring()in unattributed sources. The PythonMethodMatcher.matchesexplicitly returnsFalsewhenmethod_type.declaring_type is None, so the in-processUsesMethodgate fails — and on the wire pathTypesInUse.hasMethodUsecan't reliably match the method either.Now
_get_declaring_typereturns a non-nullFullyQualifiedin every case — falling back to the shared_UNKNOWNsingleton — soHasMethod/UsesMethodprecondition gates work against unattributed code. The function signature changes fromOptional[JavaType.FullyQualified]toJavaType.FullyQualifiedto document the new invariant. The intermediate resolution paths (Ty type-id lookup, attribute chain inference) that previously returned None now fall through to the Unknown fallback rather than short-circuiting.SearchResult.found
Adds a public
SearchResult.found(tree, description=None)static factory mirroring Java'sorg.openrewrite.marker.SearchResult.found. Returns a new tree carrying a freshSearchResultmarker — the canonical "different tree" sentinel thatCheck/CompositePreconditioninterpret as the gate matching. The nativerewrite/python/search/{IsSourceFile,UsesType,UsesMethod}visitors (added in rewrite-python: Preconditions.or_ / and_ / not_ for RPC recipes #7625) were already callingSearchResult.found(tree), which silently AttributeError'd at runtime because the helper didn't exist; this fixes that.Impact on rewrite-migrate-python#54
Locally I rebuilt rewrite-migrate-python's full test suite against this branch's editable install:
test_array_deprecations,test_cgi_parse_deprecations,test_html_parser_deprecations, …)ReplaceReTemplatewas gating onuses_methodbut matches both method and field-access forms ofre.template/re.TEMPLATE— that's a small follow-up commit on the recipe side.)Test plan
pytest rewrite-python/rewrite/tests/— 1198 passed, 11 skippedPythonTypeMapping().method_invocation_type(ast.parse("data = my_array.tostring()").body[0].value).declaring_type is _UNKNOWN✓