Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
c650292
feat(identity): callable identity plumbing, no language enabled (#2061)
DeusData Sep 25, 2026
7abaa91
chore(lint): clang-format the callable_sig.h include comment in store.c
DeusData Sep 25, 2026
d8a845e
fix(swift): preserve overload identity and label-aware call edges
DavidHLP Sep 26, 2026
7ae8300
style(swift): format overload patch
DavidHLP Sep 26, 2026
20b55ff
test(swift): cover parallel overload candidate edges
DavidHLP Sep 26, 2026
d5cb9b5
test(swift): accept signature-qualified caller names in call matrix
DavidHLP Sep 26, 2026
f200d74
fix(extraction): attribute Swift lifecycle calls
Studnicky Sep 27, 2026
19c8d07
fix(swift): unify incompatible-overload fallback across resolver paths
DavidHLP Sep 29, 2026
bbd0957
fix(pipeline): use tracked allocator for suffix lookup
DavidHLP Sep 29, 2026
2100204
fix: guard zero-length signature buffer copy
DavidHLP Sep 30, 2026
b0958c6
refactor: narrow Swift candidate variable scope
DavidHLP Sep 30, 2026
b7c8669
fix(swift): merge current callable identity plumbing
DavidHLP Oct 1, 2026
f583ad9
fix(swift): match multiple trailing closure labels
DavidHLP Oct 3, 2026
73f4475
docs(swift): record focused identity validation evidence
DavidHLP Oct 3, 2026
6fc5af9
test(swift): add standalone issue 2061 graph reproduction
DavidHLP Oct 3, 2026
ceb1914
docs(swift): record original issue 2061 graph red-green evidence
DavidHLP Oct 3, 2026
617c030
test(swift): add MCP presentation repro driver
DavidHLP Oct 3, 2026
f6c5ef6
docs(swift): record scoped MCP validation failure
DavidHLP Oct 3, 2026
eea3143
docs(swift): record index format rebuild validation
DavidHLP Oct 3, 2026
251c06a
fix(swift): integrate callable identity with current main
DavidHLP Oct 5, 2026
b4e3daf
test(swift): reproduce default-before-required argument matching
DavidHLP Oct 5, 2026
233f569
fix(swift): propagate route mounts through overload emitters
DavidHLP Oct 5, 2026
9aad2f9
fix(swift): retain default argument matching alternatives
DavidHLP Oct 5, 2026
98c3a40
style(swift): format variadic matching transition
DavidHLP Oct 5, 2026
44294f8
test(swift): preserve MCP observations through sanitizer teardown
DavidHLP Oct 5, 2026
997cb1e
refactor(swift): bound matcher transition complexity
DavidHLP Oct 5, 2026
a03131c
fix(swift): account for service signature scratch allocation
DavidHLP Oct 5, 2026
0f294df
refactor(swift): reuse signature depth tracking for closure types
DavidHLP Oct 5, 2026
39d5db4
docs(swift): publish current main integration and validation evidence
DavidHLP Oct 5, 2026
7188414
test(swift): expose generic and async identity collisions
DavidHLP Oct 5, 2026
e1eb929
fix(swift): retain generic requirements and async callable identity
DavidHLP Oct 5, 2026
5d214b3
docs(swift): archive history and provide portable graph and MCP repro
DavidHLP Oct 5, 2026
5f77b45
docs(swift): clarify fresh reproduction database requirements
DavidHLP Oct 5, 2026
6222b52
test(swift): share incompatible-call fixture across resolver paths
DavidHLP Oct 5, 2026
5d21def
test(swift): require persisted incremental repair path
DavidHLP Oct 5, 2026
6a8905e
test(swift): verify incompatible-edge assertion detects injected faults
DavidHLP Oct 5, 2026
9ea6058
style(swift): format identity regression additions
DavidHLP Oct 5, 2026
9a18323
refactor(swift): keep signature parsing within lint limits
DavidHLP Oct 5, 2026
ee61f3b
refactor(swift): remove new static analysis violations
DavidHLP Oct 5, 2026
d4f10e9
style(swift): preserve signature constant formatting
DavidHLP Oct 5, 2026
3bde72e
refactor(swift): preserve service matching order without assignment c…
DavidHLP Oct 5, 2026
f2da1f4
style(swift): format service matching table
DavidHLP Oct 5, 2026
500707c
docs(swift): publish final repair evidence and main controls
DavidHLP Oct 5, 2026
f234417
test(swift): reproduce qualified and return overload collisions
DavidHLP Oct 5, 2026
598d068
test(swift): cover return candidates and format-three migration
DavidHLP Oct 5, 2026
3113c6a
test(swift): guard returned operator and capped identities
DavidHLP Oct 5, 2026
e3cd15a
test(swift): preserve nested generic requirement boundaries
DavidHLP Oct 5, 2026
ab0dce1
fix(swift): retain qualified parameter and return identities
DavidHLP Oct 5, 2026
90bfd2e
style(swift): format overload identity regressions
DavidHLP Oct 5, 2026
7867379
refactor(swift): simplify balanced return validation
DavidHLP Oct 5, 2026
10f4769
style(swift): wrap generic boundary guard
DavidHLP Oct 5, 2026
35533b2
docs(swift): record qualified and return identity validation
DavidHLP Oct 5, 2026
6ca78d0
chore(swift): merge main and resolve indexing conflicts
DavidHLP Oct 7, 2026
f6d8c70
chore(swift): merge main PHP route resolution without conflicts
DavidHLP Oct 8, 2026
542e9e0
chore(swift): merge main and retain definition metadata
DavidHLP Oct 9, 2026
4810738
merge: resolve Swift identity conflicts with current main
DavidHLP Oct 10, 2026
a146763
fix(lint): clarify PDF duplicate node name comparison
DavidHLP Oct 10, 2026
67c46cb
fix(swift): integrate upstream candidate ranking API
DavidHLP Oct 11, 2026
2a4d50d
merge: resolve PR #2436 conflicts with main
DavidHLP Oct 13, 2026
caa4d0c
fix: pass language to parallel service edge
DavidHLP Oct 13, 2026
ba26041
fix: address CI route and sanitizer findings
DavidHLP Oct 13, 2026
49d6798
merge: sync main and resolve PR #2436 conflicts
DavidHLP Oct 14, 2026
09fcf9b
test(cypher): cap Windows UNION stress branches
DavidHLP Oct 14, 2026
fd05880
Merge branch 'main' of github.com:DeusData/codebase-memory-mcp into f…
DavidHLP Oct 14, 2026
1010bde
fix(swift): preserve distinct identities and uncapped selectors
DavidHLP Oct 15, 2026
5142a75
Merge upstream main into feat/issue-2061-swift-identity
DavidHLP Oct 15, 2026
a9e56d9
style(swift): format candidate scratch allocation
DavidHLP Oct 15, 2026
4ab447f
chore: merge main and reconcile index migrations
DavidHLP Oct 17, 2026
4885230
Merge branch 'main' into feat/issue-2061-swift-identity
DavidHLP Oct 18, 2026
468102c
Merge branch 'main' into fix/swift-init-extraction
DeusData Oct 20, 2026
71ab015
fix(extraction): keep Swift initializer edges to true targets
DeusData Oct 20, 2026
cd87073
Merge branch 'main' into fix/swift-init-extraction
DeusData Oct 20, 2026
b5b16e0
Merge origin/main into fix/swift-init-extraction
DeusData Oct 26, 2026
c9baad7
fix(swift): address callable identity review and merge main
DavidHLP Oct 26, 2026
8e91d3f
fix(swift): integrate lifecycle identities and preserve receiver inhe…
DavidHLP Oct 26, 2026
debefaf
fix(registry): bound receiver root scan by initialized length
DavidHLP Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 299 additions & 13 deletions internal/cbm/callable_sig.c

Large diffs are not rendered by default.

34 changes: 24 additions & 10 deletions internal/cbm/callable_sig.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
*
* A callable's graph identity is
*
* callable_qn := base_qn [<tparams>] (params) [cvref]
* callable_qn := base_qn [<tparams>] (params) [cvref/static/class] [async] [=>return_type]
* Swift includes generic declarations and where requirements in <tparams>
* (associated-type paths use '/' instead of '.') and appends function-level
* async after params and an explicit return type after "=>". Qualified types keep their last
* segment. These distinguish declarations, not call applicability.
*
* so overloads that share a base QN (Java/C#/C++/Kotlin/Swift/Scala/ObjC)
* become distinct nodes instead of merging into one node that collects every
Expand All @@ -22,8 +26,8 @@
* - it is whitespace-normalized: one space only between two identifier
* characters ("unsigned long", "const T&"), none elsewhere;
* - type spelling: comments, annotations and attributes are dropped;
* qualified type paths keep their last segment (java.util.List -> List,
* std::vector -> vector); "->" in function types is spelled "=>"; a
* qualified paths keep their last segment (java.util.List
* -> List, std::vector -> vector); "->" in function types is spelled "=>"; a
* variadic/rest marker is "[]" for Java (the JVM array it is) and "~"
* everywhere else; C++ top-level cv-qualifiers are dropped and array
* parameters decay to pointers, as the language itself does;
Expand All @@ -38,6 +42,7 @@
#include "arena.h"
#include "tree_sitter/api.h"
#include <stddef.h>
#include <stdint.h>

typedef enum {
CBM_CALLABLE_ID_NONE = 0, /* historical base QN, no suffix */
Expand All @@ -49,20 +54,26 @@ typedef enum {

enum { CBM_CALLABLE_SIG_MAX = 200 };

/* The identity mode a language uses for callable QNs. Every language is
* CBM_CALLABLE_ID_NONE until its enable change lands (with its index-format
* bump). Kept as a side table, like cbm_string_dispatch_suffixes, rather than
* a CBMLangSpec field: the ~160 positional lang_specs rows would all have to
* spell the new member under -Wmissing-field-initializers. */
/* The identity mode a language uses for callable QNs. Languages remain
* CBM_CALLABLE_ID_NONE until their enable change lands with an index-format
* bump; Swift is enabled by #2061. Kept as a side table, like
* cbm_string_dispatch_suffixes, rather than a CBMLangSpec field: the ~160
* positional lang_specs rows would all have to spell the new member under
* -Wmissing-field-initializers. */
CBMCallableIdentity cbm_callable_identity(CBMLanguage lang);

/* Swift parameter defaults are call-resolution metadata, not graph identity.
* Returns a bit per parameter; count > 64 is reported as 255. */
uint64_t cbm_swift_default_mask(TSNode func_node, const char *source, uint8_t *count);
/* Uncapped parameter spelling: matching must not parse a hashed identity. */
const char *cbm_swift_selector(CBMArena *a, TSNode func_node, const char *source);
/* The identity suffix for the callable at `func_node` in the language's own
* mode, or NULL when that mode is NONE (or the node carries no parameter
* information the mode can use). Arena-owned. */
const char *cbm_callable_sig(CBMArena *a, TSNode func_node, const char *source, CBMLanguage lang);

/* Same, with an explicit mode — the builder the enable changes and the golden
* tables exercise before a language is switched on. */
/* Same, with an explicit mode — the builder's golden tables exercise modes
* independently of each language's production enablement. */
const char *cbm_callable_sig_mode(CBMArena *a, TSNode func_node, const char *source,
CBMLanguage lang, CBMCallableIdentity mode);

Expand All @@ -72,6 +83,9 @@ const char *cbm_callable_sig_mode(CBMArena *a, TSNode func_node, const char *sou
* name, not a suffix. NULL -> 0. */
size_t cbm_qn_callable_base_len(const char *qn);

/* Top-level declaration return marker; strlen(suffix) if absent, 0 if malformed. */
size_t cbm_callable_return_offset(const char *suffix);

/* The inverse anchored to the callable's bare `name` (the node's name
* column): the suffix is stripped only when the base QN is `name` or ends in
* "." / "::" + `name`. Other QN text can end in ')' as well — a Java field
Expand Down
25 changes: 23 additions & 2 deletions internal/cbm/cbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ typedef struct {
* qualified_name (base QN = the first qn_sig_off bytes); 0 = no suffix.
* Always 0 until a language enables its callable_identity mode. */
uint32_t qn_sig_off;
/* Call matching: defaulted parameters, indexed in declaration order. */
uint64_t param_default_mask;
uint8_t selector_param_count;
const char *call_selector;
/* C# only: declared namespace of a TOP-LEVEL type (NULL for nested types,
* the global namespace and every other language). Per type, because the
* file-level namespace_name records only a file's first namespace. */
Expand Down Expand Up @@ -325,6 +329,9 @@ typedef struct {
} CBMCallArg;

#define CBM_MAX_CALL_ARGS 8
/* Swift trailing-closure capture bound (#2061): more than this on one call
* marks the call truncated and the overload matcher fails closed. */
#define CBM_MAX_TRAILING_CLOSURES 8

/* The qualified name of a C-preprocessor macro (`#define NAME ...` in C, C++,
* CUDA, Objective-C, GLSL, ISPC) is `<module QN>.<NAME>#macro`. C keeps macros
Expand Down Expand Up @@ -381,6 +388,20 @@ typedef struct {
// (self.compiler.apply_converters()). An object the
// class owns, not a parameter: read by the weak-member
// guard's unique-name exemption. Default false.
bool has_trailing_closure;
bool args_truncated;
/* Swift multi-trailing-closure capture (#2061). `has_trailing_closure`
* stays the "there is at least one trailing closure" flag manual callers
* and existing tests set; `trailing_closure_count` is the actual number
* captured (0 => fall back to the bool, treated as one unlabelled closure).
* `trailing_closure_labels[i]` is closure i's argument label from the
* grammar's `lambda_literal (simple_identifier ':')*` sequence (NULL when
* unlabelled; entry 0 is always unlabelled). More closures than
* CBM_MAX_TRAILING_CLOSURES sets `trailing_closure_truncated`, and the
* overload matcher then fails closed rather than guessing a partial set. */
uint8_t trailing_closure_count;
bool trailing_closure_truncated;
const char **trailing_closure_labels;
} CBMCall;

// What an import statement names, when the syntax says so. Only PHP's
Expand Down Expand Up @@ -539,8 +560,8 @@ typedef struct {

typedef struct {
const char *var_name; // variable being assigned
const char *type_name; // class/type name of RHS constructor
const char *enclosing_func_qn; // QN of enclosing function
const char *type_name; // declared type or RHS constructor type
const char *enclosing_func_qn; // enclosing function, class, or module QN
} CBMTypeAssign;

// String reference: URL, config key, or async target found in source.
Expand Down
186 changes: 186 additions & 0 deletions internal/cbm/extract_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -2486,6 +2486,7 @@ static void process_keyword_arg(CBMExtractCtx *ctx, TSNode arg_node, CBMCallArg
}
}

static TSNode swift_argument_value(TSNode arg);
static const char *extract_string_value(CBMExtractCtx *ctx, TSNode val_node, bool url_context);

/* Whether a call's callee is an HTTP client or a global fetch, which selects
Expand Down Expand Up @@ -2585,6 +2586,26 @@ static void extract_call_args(CBMExtractCtx *ctx, TSNode args, CBMCall *call) {
CBMCallArg *ca = &call->args[call->arg_count];
memset(ca, 0, sizeof(*ca));

if (ctx->language == CBM_LANG_SWIFT && strcmp(ak, "value_argument") == 0) {
TSNode first = ts_node_named_child(arg_node, 0);
if (!ts_node_is_null(first) &&
strcmp(ts_node_type(first), "value_argument_label") == 0) {
TSNode label = ts_node_named_child(first, 0);
if (ts_node_is_null(label)) {
label = first;
}
ca->keyword = cbm_node_text(ctx->arena, label, ctx->source);
if (ca->keyword) {
size_t n = strlen(ca->keyword);
if (n > 0 && ca->keyword[n - SKIP_ONE] == ':') {
ca->keyword = cbm_arena_strndup(ctx->arena, ca->keyword, n - SKIP_ONE);
}
}
}
arg_node = swift_argument_value(arg_node);
ak = ts_node_type(arg_node);
}

if (strcmp(ak, "keyword_argument") == 0 || strcmp(ak, "pair") == 0) {
process_keyword_arg(ctx, arg_node, ca);
ca->index = positional_idx++;
Expand Down Expand Up @@ -3897,6 +3918,79 @@ static TSNode swift_call_args(TSNode node) {
return cbm_find_child_by_kind(suffix, "value_arguments");
}

/* Store one bounded trailing-closure label; closure zero is unlabelled. */
static void swift_store_trailing_label(CBMExtractCtx *ctx, CBMCall *call, uint32_t index,
const char *label, bool has_label) {
if (index == 0) {
call->has_trailing_closure = true;
return;
}
if (index >= CBM_MAX_TRAILING_CLOSURES) {
call->trailing_closure_truncated = true;
return;
}
if (!call->trailing_closure_labels) {
size_t bytes = CBM_MAX_TRAILING_CLOSURES * sizeof(char *);
call->trailing_closure_labels = cbm_arena_calloc(ctx->arena, bytes);
}
if (!call->trailing_closure_labels) {
call->trailing_closure_truncated = true;
return;
}
call->trailing_closure_labels[index] = label;
if (has_label && !label) {
call->trailing_closure_truncated = true;
}
}

/* Swift records trailing closures on the call_suffix: the hidden
* _fn_call_lambda_arguments rule inlines to
* `lambda_literal (simple_identifier ':')*`, so every closure literal, and the
* label that precedes all but the first, sit flat among the suffix's children
* (after an optional value_arguments). Each lambda_literal is a trailing
* closure; a simple_identifier directly before a closure is that closure's
* label. Closure 0 is always unlabelled. More closures than the bounded
* storage marks the call truncated so the overload matcher fails closed. */
static void swift_capture_trailing_closures(CBMExtractCtx *ctx, TSNode call_node, TSNode suffix,
CBMCall *call) {
if (ts_node_has_error(call_node)) {
call->trailing_closure_truncated = true;
}
uint32_t children = ts_node_child_count(suffix) + ts_node_child_count(call_node);
uint32_t closures = 0;
const char *pending_label = NULL;
bool has_pending_label = false;
for (uint32_t i = 0; i < children; i++) {
uint32_t suffix_children = ts_node_child_count(suffix);
TSNode child = i < suffix_children ? ts_node_child(suffix, i)
: ts_node_child(call_node, i - suffix_children);
if (i >= suffix_children && ts_node_start_byte(child) < ts_node_end_byte(suffix)) {
continue;
}
const char *kind = ts_node_type(child);
if (ts_node_is_missing(child) || ts_node_has_error(child)) {
call->trailing_closure_truncated = true;
}
if (strcmp(kind, "lambda_literal") == 0) {
swift_store_trailing_label(ctx, call, closures, pending_label, has_pending_label);
closures++;
pending_label = NULL;
has_pending_label = false;
} else if (strcmp(kind, "simple_identifier") == 0) {
if (has_pending_label) {
call->trailing_closure_truncated = true;
}
pending_label = cbm_node_text(ctx->arena, child, ctx->source);
has_pending_label = true;
}
}
if (has_pending_label) {
call->trailing_closure_truncated = true;
}
call->trailing_closure_count =
(uint8_t)(closures > CBM_MAX_TRAILING_CLOSURES ? CBM_MAX_TRAILING_CLOSURES : closures);
}

static bool node_has_token(TSNode node, const char *token) {
uint32_t count = ts_node_child_count(node);
for (uint32_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -4278,6 +4372,70 @@ static TSNode language_specific_callee_leaf(CBMLanguage language, TSNode expr,
return terminal_callee_leaf(ctx, expr);
}

/* `Base.init` for a `super.init(...)` call: Base is the first entry of the
* enclosing class's inheritance clause, where Swift requires the superclass to
* stand. The class node is carried by the walk, so no ancestor climb. NULL (no
* call) outside a class, without a clause, or when the entry does not read as
* a plain type name -- a lower-case or attributed root would pass the
* registry's receiver-chain check and bind by short name, which is the false
* edge this exists to prevent. */
static const char *swift_superclass_init_callee(CBMExtractCtx *ctx, const WalkState *state) {
TSNode cls = state ? state->enclosing_class_node : (TSNode){0};
if (ts_node_is_null(cls) || strcmp(ts_node_type(cls), "class_declaration") != 0) {
return NULL;
}
TSNode spec = cbm_find_child_by_kind(cls, "inheritance_specifier");
char *base = ts_node_is_null(spec) ? NULL : cbm_node_text(ctx->arena, spec, ctx->source);
if (!base || base[0] < 'A' || base[0] > 'Z') {
return NULL;
}
size_t len = strcspn(base, "<"); /* Base<T> names Base */
for (size_t i = 0; i < len; i++) {
if (!isalnum((unsigned char)base[i]) && base[i] != '_' && base[i] != '.') {
return NULL;
}
}
base[len] = '\0';
return cbm_arena_sprintf(ctx->arena, "%s.init", base);
}

/* True for a Swift initializer callee `T.init` (T non-empty). */
static bool swift_callee_is_initializer(const char *callee) {
static const char suffix[] = ".init";
size_t n = callee ? strlen(callee) : 0;
return n > sizeof(suffix) - SKIP_ONE &&
strcmp(callee + n - (sizeof(suffix) - SKIP_ONE), suffix) == 0;
}

/* Swift initializer delegation (#2379). `super.init(...)` and `self.init(...)`
* name no type, and a lower-case receiver passes the registry's receiver-chain
* check, so a short-name match binds them to whichever project `init` is
* nearest: a nested type's, a sibling type's, or the caller's own. On
* Alamofire all 8 such edges were false.
*
* `super.init` is rewritten to name the superclass (`Base.init`), so the
* qualified strategies place it on the project's Base.init. When Base is not
* in the project (UIViewController, NSObject) nothing places it, and the
* initializer guard in handle_calls keeps a short-name guess from doing so.
*
* `self.init` delegates to another initializer of the caller's own type.
* Keep #2395's no-edge policy until overload-aware delegation is addressed
* separately; the delegated initializer can live outside the project
* (`extension Notification { init(...) { self.init(...) } }` calls Foundation's). */
static const char *resolve_swift_delegating_init(CBMExtractCtx *ctx, const WalkState *state,
const char *callee) {
if (ctx->language != CBM_LANG_SWIFT || !callee) {
return callee;
}
if (strcmp(callee, "self.init") == 0) {
return NULL;
}
if (strcmp(callee, "super.init") == 0) {
return swift_superclass_init_callee(ctx, state);
}
return callee;
}

// Produce the textual callee and the AST occurrence from one operation. The
// generic fallback retains the former field/terminal behavior, while grammars
// whose extractor uses a sibling, a special field, or a synthetic literal are
Expand All @@ -4288,6 +4446,7 @@ static CBMPrimaryCalleeSelection select_primary_callee(CBMExtractCtx *ctx, TSNod
CBMPrimaryCalleeSelection selection = {0};
selection.name = extract_callee_name(ctx->arena, node, ctx->source, ctx->language);
selection.name = resolve_objectscript_callee(ctx, node, state, selection.name);
selection.name = resolve_swift_delegating_init(ctx, state, selection.name);
if (!selection.name || !selection.name[0]) {
return selection;
}
Expand Down Expand Up @@ -4511,6 +4670,16 @@ CBMInvocationDescriptor handle_calls(CBMExtractCtx *ctx, TSNode node, const CBML
call.is_method = true;
}
}
// Swift initializer guard (#2379; same direction). Flag `T.init(...)`,
// as written or as a rewritten super.init. Nearly every type has an
// `init`, so a short-name match onto one is a guess: with a project
// module imported, `UIViewController.init` bound an unrelated
// project initializer. The registry's qualified / same-module /
// import strategies still place T.init when T is a project type.
// No other Swift call carries the flag.
if (ctx->language == CBM_LANG_SWIFT && swift_callee_is_initializer(call.callee_name)) {
call.is_method = true;
}

TSNode args = ts_node_child_by_field_name(node, TS_FIELD("arguments"));
/* tree-sitter-elixir attaches NO field name to a call's arguments
Expand All @@ -4537,6 +4706,23 @@ CBMInvocationDescriptor handle_calls(CBMExtractCtx *ctx, TSNode node, const CBML
if (ts_node_is_null(args) && ctx->language == CBM_LANG_SWIFT) {
args = swift_call_args(node);
}
if (ctx->language == CBM_LANG_SWIFT) {
TSNode suffix = cbm_find_child_by_kind(node, "call_suffix");
if (!ts_node_is_null(suffix)) {
swift_capture_trailing_closures(ctx, node, suffix, &call);
}
uint32_t value_arg_count = 0;
if (!ts_node_is_null(args)) {
uint32_t named_count = ts_node_named_child_count(args);
for (uint32_t ai = 0; ai < named_count; ai++) {
TSNode arg = ts_node_named_child(args, ai);
value_arg_count += strcmp(ts_node_type(arg), "value_argument") == 0;
}
}
if (value_arg_count > CBM_MAX_CALL_ARGS) {
call.args_truncated = true;
}
}
if (!ts_node_is_null(args)) {
call.first_string_arg = extract_url_or_topic_arg(ctx, args, call.callee_name);
/* #1146: a Laravel registration's slashless URI ('users', '')
Expand Down
Loading
Loading