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
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
package languages
|
|
|
|
import (
|
|
"regexp"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
"github.com/zzet/gortex/internal/parser"
|
|
)
|
|
|
|
// objcSelectorRe matches an Objective-C @selector(...) literal, capturing the
|
|
// full selector including its colons (`doThing:`, `setX:y:`).
|
|
var objcSelectorRe = regexp.MustCompile(`@selector\s*\(\s*([A-Za-z_][A-Za-z0-9_:]*)\s*\)`)
|
|
|
|
// captureObjCSelectors records each @selector(sel) literal whose selector names
|
|
// a method declared in the same file as a function-as-value reference, so the
|
|
// targeted method is reachable through the selector even though no direct call
|
|
// edge exists. Objective-C is regex-extracted, so this is a focused scan rather
|
|
// than the tree-walking captureFnValueCandidates pass; it mirrors the Swift
|
|
// #selector handling (recv hint <self>, resolved against same-file methods).
|
|
func captureObjCSelectors(src []byte, methodRanges []objcSpan, filePath string, result *parser.ExtractionResult) {
|
|
funcs := map[string]bool{}
|
|
for _, n := range result.Nodes {
|
|
if n == nil || n.FilePath != filePath {
|
|
continue
|
|
}
|
|
if n.Kind == graph.KindMethod || n.Kind == graph.KindFunction {
|
|
funcs[n.Name] = true
|
|
}
|
|
}
|
|
var cands []FnValueCandidate
|
|
seen := map[string]bool{}
|
|
for _, m := range objcSelectorRe.FindAllSubmatchIndex(src, -1) {
|
|
sel := string(src[m[2]:m[3]])
|
|
if sel == "" || !funcs[sel] {
|
|
continue
|
|
}
|
|
line := lineAt(src, m[0])
|
|
fromID := objcEnclosing(methodRanges, line)
|
|
if fromID == "" {
|
|
continue
|
|
}
|
|
key := fromID + "\x00" + sel
|
|
if seen[key] {
|
|
continue
|
|
}
|
|
seen[key] = true
|
|
cands = append(cands, FnValueCandidate{
|
|
FromID: fromID, Name: sel, FilePath: filePath, Line: line,
|
|
Form: "selector", RecvHint: "<self>", Lang: "objc",
|
|
})
|
|
}
|
|
EmitFnValueCandidates(result, cands)
|
|
}
|