MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / parse_narrowing_one

Function parse_narrowing_one

internal/cbm/lsp/php_lsp.c:1917–2063  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1915}
1916
1917static int parse_narrowing_one(PHPLSPContext *ctx, TSNode cond, php_narrowing_t *out) {
1918 if (ts_node_is_null(cond))
1919 return 0;
1920 const char *kind = ts_node_type(cond);
1921 if (strcmp(kind, "parenthesized_expression") == 0) {
1922 uint32_t nc = ts_node_child_count(cond);
1923 for (uint32_t i = 0; i < nc; i++) {
1924 TSNode c = ts_node_child(cond, i);
1925 if (!ts_node_is_null(c) && ts_node_is_named(c)) {
1926 return parse_narrowing_one(ctx, c, out);
1927 }
1928 }
1929 return 0;
1930 }
1931
1932 /* `$x instanceof Foo` — emitted as binary_expression with operator
1933 * "instanceof" in tree-sitter-php. */
1934 if (strcmp(kind, "binary_expression") == 0) {
1935 TSNode left = ts_node_child_by_field_name(cond, "left", 4);
1936 TSNode op = ts_node_child_by_field_name(cond, "operator", 8);
1937 TSNode right = ts_node_child_by_field_name(cond, "right", 5);
1938 if (ts_node_is_null(left) || ts_node_is_null(right))
1939 return false;
1940 char *opt = !ts_node_is_null(op) ? php_node_text(ctx, op) : NULL;
1941 if (opt && strcmp(opt, "instanceof") == 0) {
1942 if (!node_is(left, "variable_name"))
1943 return false;
1944 char *vt = php_node_text(ctx, left);
1945 if (!vt)
1946 return false;
1947 const char *vname = (vt[0] == '$') ? vt + 1 : vt;
1948 char *rt = php_node_text(ctx, right);
1949 if (!rt)
1950 return false;
1951 const char *resolved = php_resolve_class_name(ctx, rt);
1952 if (!resolved)
1953 return false;
1954 out->var_name = cbm_arena_strdup(ctx->arena, vname);
1955 out->type = cbm_type_named(ctx->arena, resolved);
1956 return true;
1957 }
1958 /* `$x !== null` / `$x != null` / `null !== $x` — narrow to "non-null":
1959 * we keep the existing scope type, so this is a no-op for type
1960 * purposes but suppresses null branches downstream. We don't
1961 * subtract nullable so just return false here. */
1962 }
1963
1964 /* `is_string($x)` / `is_int($x)` / `array_key_exists(...)` /
1965 * `method_exists($x, 'foo')` / `is_a($x, Foo::class)` / ... */
1966 if (strcmp(kind, "function_call_expression") == 0) {
1967 TSNode fn = ts_node_child_by_field_name(cond, "function", 8);
1968 TSNode args = ts_node_child_by_field_name(cond, "arguments", 9);
1969 if (ts_node_is_null(fn))
1970 return false;
1971 char *name = php_node_text(ctx, fn);
1972 if (!name)
1973 return false;
1974 /* `is_a($x, Foo::class)` and `is_a($x, 'Foo')` narrow $x to Foo. */

Callers 1

parse_narrowing_collectFunction · 0.85

Calls 7

php_node_textFunction · 0.85
node_isFunction · 0.85
php_resolve_class_nameFunction · 0.85
cbm_type_namedFunction · 0.85
is_func_to_builtinFunction · 0.85
cbm_type_builtinFunction · 0.85
cbm_arena_strdupFunction · 0.50

Tested by

no test coverage detected