Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

69 lines
3.2 KiB
Go

package languages
import (
"regexp"
"github.com/zzet/gortex/internal/parser"
)
// rnNativeEventTransport is the pub/sub transport label for a React Native
// native-module event channel: an Objective-C / Swift `sendEventWithName:`
// emit paired with a JS `NativeEventEmitter(...).addListener` handler. The
// `rn_` prefix marks it as a native cross-language bridge the event-channel
// synthesizer pairs (and the contracts broker layer ignores).
const rnNativeEventTransport = "rn_native_event"
// rnObjCSendEventRe matches an Objective-C `[self sendEventWithName:@"Name" …]`
// RCTEventEmitter emit, capturing the event name string.
var rnObjCSendEventRe = regexp.MustCompile(`sendEventWithName:\s*@"([^"]+)"`)
// rnSendEventWrapperRe matches a paren-form `sendEvent(...)` emit -- both the
// Swift labelled `sendEvent(withName: "Name", ...)` and a custom helper
// wrapper `sendEvent(reactContext, "Name", body)` -- capturing the first
// literal string argument as the event name. The `[^;{}]` guard keeps a
// single match from spanning a statement boundary.
var rnSendEventWrapperRe = regexp.MustCompile(`\bsendEvent\s*\([^;{}]*?"([^"]+)"`)
// mineRNNativeEmits scans native source for React Native event-emit sites and
// records one pub/sub publish per emit on the rn_native_event channel,
// attributed to the enclosing function via callerLookup. The event-channel
// synthesizer then pairs each native emit with the JS addListener handler on
// the same event name. File-scope emits (callerLookup returns "") are dropped.
func mineRNNativeEmits(src []byte, re *regexp.Regexp, callerLookup func(line int) string, filePath, language string, result *parser.ExtractionResult) {
matches := re.FindAllSubmatchIndex(src, -1)
if len(matches) == 0 {
return
}
events := make([]pubsubEvent, 0, len(matches))
for _, m := range matches {
name := string(src[m[2]:m[3]])
if name == "" {
continue
}
events = append(events, pubsubEvent{
role: pubsubRolePublish,
transport: rnNativeEventTransport,
topic: name,
method: "sendEventWithName",
line: lineAt(src, m[0]),
})
}
emitPubsubEvents(events, callerLookup, filePath, language, result)
}
// rnJVMEmitRe matches an Android React Native device-event emit chain,
// reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java).emit("Name", ...)
// (Kotlin) / ....RCTDeviceEventEmitter.class).emit("Name", ...) (Java), capturing
// the event name.
var rnJVMEmitRe = regexp.MustCompile(`getJSModule\s*\([^;]*?\)\s*\.\s*emit\s*\(\s*"([^"]+)"`)
// mineRNJVMEmits scans Java/Kotlin source for React Native native event emits --
// the getJSModule(...).emit("Name", ...) device-event-emitter chain and the
// common sendEvent(reactContext, "Name", ...) helper wrapper -- and records each
// as a publish on the rn_native_event channel. The two forms are syntactically
// disjoint, so neither double-counts the other.
func mineRNJVMEmits(src []byte, callerLookup func(line int) string, filePath, language string, result *parser.ExtractionResult) {
mineRNNativeEmits(src, rnJVMEmitRe, callerLookup, filePath, language, result)
mineRNNativeEmits(src, rnSendEventWrapperRe, callerLookup, filePath, language, result)
}