IMPORTS edges carry exactly one imported symbol's local_name (#768): two * named imports from the same specifier resolve to the same (source, * target) pair but are distinct symbols. Key on local_name too so the * second import doesn't dedup-collide with and overwrite the first — * every pass that walks IMPORTS edges (pass_calls.c, pass_usages.c, * pass_semantic.c, pass_lsp_cross.c) expects o
| 173 | * JSON slice (control characters must be \u-escaped in JSON), so hash keys |
| 174 | * can never collide with verbatim keys. */ |
| 175 | static void make_edge_key(char *buf, size_t bufsz, int64_t src, int64_t tgt, const char *type, |
| 176 | const char *properties_json) { |
| 177 | if (properties_json && strcmp(type, "IMPORTS") == 0) { |
| 178 | static const char local_name_key[] = "\"local_name\":\""; |
| 179 | const char *ln = strstr(properties_json, local_name_key); |
| 180 | if (ln) { |
| 181 | ln += sizeof(local_name_key) - 1; |
| 182 | const char *end = strchr(ln, '"'); |
| 183 | size_t ln_len = end ? (size_t)(end - ln) : strlen(ln); |
| 184 | int n = snprintf(buf, bufsz, "%lld:%lld:%s:%.*s", (long long)src, (long long)tgt, type, |
| 185 | (int)ln_len, ln); |
| 186 | if (n < 0 || (size_t)n >= bufsz) { |
| 187 | snprintf(buf, bufsz, "%lld:%lld:%s:\x01%016llx", (long long)src, (long long)tgt, |
| 188 | type, (unsigned long long)fnv1a64(ln, ln_len)); |
| 189 | } |
| 190 | return; |
| 191 | } |
| 192 | } |
| 193 | snprintf(buf, bufsz, "%lld:%lld:%s", (long long)src, (long long)tgt, type); |
| 194 | } |
| 195 | |
| 196 | static void make_src_type_key(char *buf, size_t bufsz, int64_t src, const char *type) { |
| 197 | snprintf(buf, bufsz, "%lld:%s", (long long)src, type); |
no test coverage detected