Broaden cross-language resolution, framework bridges, and reference capture - #177
Merged
Conversation
Extend the string-callable higher-order-function set (array_udiff and friends, forward_static_call, set_exception_handler, ob_start, iterator_apply, is_callable, and more). For preg_replace_callback_array, resolve the value side of each pattern => callback array element rather than scanning the array flat, so regex-pattern keys are not mistaken for callables.
…s, and class-name fallback
Widen the Expo Modules DSL scan beyond Function/AsyncFunction to Property,
Events, and Constants members, tolerate a generic clause between the
keyword and its argument list (AsyncFunction<Int>("x")), and attribute
members of a definition() body that never calls Name() to their enclosing
class XxxModule (the Module suffix stripped) instead of dropping them.
…jective-C Recognize a paren-form sendEvent(reactContext, "Name", body) helper as a React Native native event emit, not just the labelled sendEvent(withName:) / sendEventWithName: forms. Swift reuses the lenient wrapper regex (a superset of the labelled form); Objective-C mines it as a separate pass since the paren and bracket forms are syntactically disjoint and so do not double-count.
Wire the React Native native-event miner into the Java and Kotlin
extractors. Captures the Android device-event emitter chain
getJSModule(RCTDeviceEventEmitter::class.java).emit("Name", ...) (and the
Java .class form) and the sendEvent(reactContext, "Name", ...) helper
wrapper, so Android native emits share the rn_native_event topic node with
the JS NativeEventEmitter addListener subscribers.
Route the C++ extractor through the function-as-value capture pass and give C++ its own value-position spec: peel the address-of pointer_expression and recognize a qualified_identifier so register(&handler) and bind(&Foo::method) each yield a function-value reference (the pointer-to-member resolving ungated, since it names a method of another class).
Scan Objective-C source for @selector(sel) literals and record each whose selector names a same-file method as a function-as-value reference, so the targeted method is reachable through performSelector and target/action wiring even though no direct call edge exists.
Route the Lua and Luau extractors through the function-as-value capture pass and give them a value-position spec, so a bare setCallback(onClick) and a table-member register(handlers.onTick) each yield a function-value reference (the dot_index_expression resolving to its trailing field name).
An @objcMembers class exposes every member to Objective-C implicitly. Stamp each member's objc_selector as if it were @objc unless it opts out with @nonobjc, deriving method and property accessor selectors the same way the explicit @objc path does.
Capture the adopted-protocol list of an Objective-C @interface and the @objc flag of a Swift protocol, then teach the Swift<->ObjC bridge synthesizer to emit a cross-language EdgeImplements from an ObjC class to the Swift @objc protocol it conforms to. Gated on the protocol being @objc.
Detect createEffect(() => this.actions$.pipe(ofType(SomeAction), ...)) in the JS/TS extractors, tag the effect node, and stamp a placeholder call per ofType action; a new framework synthesizer resolves each to the action creator / type it reacts to. Lets navigation and find_usages link a registered effect to the action that triggers it.
A $foo read in Svelte markup where foo is an imported store now binds the component to that store import (its subscribe contract) instead of dangling. Svelte 5 runes are excluded since they are framework macros, not stores, and the existing rune path is untouched.
…te attributes
Read a C# controller class-level [Route("api/[controller]")] (expanding the [controller]/[action] tokens) and prefix-join it onto each relative method route, while an absolute /... or ~/... template still ignores the prefix per ASP.NET. Also capture a verb-less method [Route("...")] as a route with an unconstrained verb.
Capture the receiver expression of a C++ member call and feed it through the shared chained-receiver walker, so a factory chain builder().withX().build() stamps the resolved receiver_type when the hop is locally typed and preserves receiver_expr for the graph-aware resolver otherwise.
Carry the receiver object of a PHP member call (-> normalised to .) through the shared chained-receiver walker, so a factory chain builder()->withX()->build() stamps the resolved receiver_type when locally typed and preserves receiver_expr for the graph-aware resolver otherwise.
…eiver type Detect a Swift navigation-expression member call (the .method() of a chain) in addition to the bare-identifier call the query already matched, gated to chains whose receiver is itself a call so ordinary obj.method() is untouched. Feed the receiver through the shared walker so builder().withX().build() resolves the chained receiver type.
Carry the object of a Scala field-expression call (the receiver the method is selected on) through the shared chained-receiver walker, so a factory chain builder().withX().build() stamps the resolved receiver_type when locally typed and preserves receiver_expr for the graph-aware resolver otherwise.
Add a factory-chain pass that emits a member call per chained .method(...) whose receiver is itself a call (builder().withX().build()) and carries the receiver text through the shared chained-receiver walker. The main call walk stops at the first call and dropped these segments; gated on a call-bearing receiver so plain recv.method() is left to it and not double-counted.
Emit a member call for a Pascal exprCall whose callee is an exprDot (recv.Method()) -- the chained segments the bare-callee path dropped -- gated to a call-bearing receiver, and carry the receiver text through the shared chained-receiver walker so Builder().WithX().Build() resolves the chain.
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
Broadens Gortex's cross-language code intelligence with a batch of independent extractor / resolver / route improvements — one commit each, every one fixture-backed and verified against the live graph. The full
go test -race ./...suite is green andgolangci-lintis clean on every touched package; no wire-contract change (onlyMetakeys added).Function-as-value & reference capture
array_udiffand friends,forward_static_call,set_exception_handler,ob_start,iterator_apply,is_callable, …); forpreg_replace_callback_array, resolve the value side of eachpattern => callbackelement.&fnand&Cls::method(pointer-to-member) as function-value references.@selector(...)literals as function-value references to the named method.tbl.method.React Native / Expo / mobile
sendEvent(ctx, "Name", body)wrapper emit (Swift/ObjC) and mine native→JS emits from Java/Kotlin (getJSModule(...).emitchain + thesendEventhelper), so Android/iOS native emits share the event topic node with JSaddListenersubscribers.Property/Constants/Eventsmembers, tolerate a generic clause (AsyncFunction<Int>("x")), and attribute members of adefinition()body with noName()to its enclosingXxxModuleclass.Swift ↔ Objective-C interop
@objcMembers— propagate implicit Objective-C exposure to a class's members (with the@nonobjcopt-out).@objc protocol— emit a cross-languageimplementsedge from an Objective-C@interfaceto the Swift@objcprotocol it adopts.Framework dispatch & resolution
createEffect(() => actions$.pipe(ofType(X)))effect to the actionXit reacts to.$storeauto-subscription in markup to the imported store (runes untouched).[Route("api/[controller]")]onto each relative method route (an absolute/.../~/...template still ignores the prefix, per ASP.NET), and capture a verb-less method[Route("...")].Factory-chain receiver typing
builder().withX().build()resolves the chained receiver type (or preserves the receiver expression for the graph-aware resolver when a hop isn't locally typed), across C++, PHP, Swift, Scala, Dart, and Pascal. The factory-chain work covers the languages whose call syntax fits the shared.-chain machinery; C (no member-call chains) and Objective-C (bracket message sends) are not applicable.Verification
go test -race ./...: green (0 failures / panics / races).golangci-lint run: clean on all touched packages.