| 1260 | } |
| 1261 | |
| 1262 | static const CBMType *eval_binary(JavaLSPContext *ctx, TSNode node) { |
| 1263 | /* Determine operator. tree-sitter-java exposes it as a child token. */ |
| 1264 | char *op = NULL; |
| 1265 | uint32_t cn = ts_node_child_count(node); |
| 1266 | for (uint32_t i = 0; i < cn; i++) { |
| 1267 | TSNode c = ts_node_child(node, i); |
| 1268 | if (ts_node_is_named(c)) |
| 1269 | continue; |
| 1270 | op = java_node_text(ctx, c); |
| 1271 | break; |
| 1272 | } |
| 1273 | /* Fallback when the unnamed-child trick fails (older grammars). */ |
| 1274 | if (!op) |
| 1275 | op = ""; |
| 1276 | |
| 1277 | if (strcmp(op, "==") == 0 || strcmp(op, "!=") == 0 || strcmp(op, "<") == 0 || |
| 1278 | strcmp(op, ">") == 0 || strcmp(op, "<=") == 0 || strcmp(op, ">=") == 0 || |
| 1279 | strcmp(op, "&&") == 0 || strcmp(op, "||") == 0) { |
| 1280 | return cbm_type_builtin(ctx->arena, "boolean"); |
| 1281 | } |
| 1282 | if (strcmp(op, "+") == 0 && is_string_concat(ctx, node)) { |
| 1283 | return cbm_type_named(ctx->arena, "java.lang.String"); |
| 1284 | } |
| 1285 | /* Numeric promotion — keep LHS for simplicity. */ |
| 1286 | TSNode lhs = ts_node_child_by_field_name(node, "left", 4); |
| 1287 | return java_eval_expr_type(ctx, lhs); |
| 1288 | } |
| 1289 | |
| 1290 | static const CBMType *eval_unary(JavaLSPContext *ctx, TSNode node) { |
| 1291 | /* `!x` → boolean; `-x` / `~x` / ++ / -- preserve the operand type. */ |
no test coverage detected