@lzehrung/codegraph 2.3.8 → 2.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/codegraph-skill/codegraph/SKILL.md +3 -0
  2. package/dist/agent/query-index/content.d.ts.map +1 -1
  3. package/dist/agent/query-index/content.js +8 -4
  4. package/dist/agent/query-index/content.js.map +1 -1
  5. package/dist/agent/renamePreview.js +4 -3
  6. package/dist/agent/renamePreview.js.map +1 -1
  7. package/dist/bin/cli.js +432 -118
  8. package/dist/bin/queryIndexWorker.js +32 -13
  9. package/dist/documentLinks/check.d.ts.map +1 -1
  10. package/dist/documentLinks/check.js +5 -3
  11. package/dist/documentLinks/check.js.map +1 -1
  12. package/dist/duplicates/units.d.ts.map +1 -1
  13. package/dist/duplicates/units.js +23 -8
  14. package/dist/duplicates/units.js.map +1 -1
  15. package/dist/graph-builder.d.ts.map +1 -1
  16. package/dist/graph-builder.js +2 -2
  17. package/dist/graph-builder.js.map +1 -1
  18. package/dist/graph-edge-collector.d.ts.map +1 -1
  19. package/dist/graph-edge-collector.js +19 -14
  20. package/dist/graph-edge-collector.js.map +1 -1
  21. package/dist/graphs/unresolved.d.ts.map +1 -1
  22. package/dist/graphs/unresolved.js +12 -4
  23. package/dist/graphs/unresolved.js.map +1 -1
  24. package/dist/impact/callCompatibility.js +2 -2
  25. package/dist/impact/callCompatibility.js.map +1 -1
  26. package/dist/impact/map.js +5 -5
  27. package/dist/impact/map.js.map +1 -1
  28. package/dist/indexer/build-cache/module-cache.js +2 -2
  29. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  30. package/dist/indexer/build-index.d.ts.map +1 -1
  31. package/dist/indexer/build-index.js +3 -3
  32. package/dist/indexer/build-index.js.map +1 -1
  33. package/dist/indexer/build-workers.d.ts +4 -0
  34. package/dist/indexer/build-workers.d.ts.map +1 -1
  35. package/dist/indexer/build-workers.js +9 -5
  36. package/dist/indexer/build-workers.js.map +1 -1
  37. package/dist/indexer/navigation-references.d.ts.map +1 -1
  38. package/dist/indexer/navigation-references.js +2 -2
  39. package/dist/indexer/navigation-references.js.map +1 -1
  40. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  41. package/dist/indexer/navigation-resolve.js +77 -66
  42. package/dist/indexer/navigation-resolve.js.map +1 -1
  43. package/dist/indexer/navigation.d.ts.map +1 -1
  44. package/dist/indexer/navigation.js +6 -4
  45. package/dist/indexer/navigation.js.map +1 -1
  46. package/dist/indexer/parse-context.d.ts +1 -1
  47. package/dist/indexer/parse-context.d.ts.map +1 -1
  48. package/dist/indexer/parse-context.js +6 -2
  49. package/dist/indexer/parse-context.js.map +1 -1
  50. package/dist/indexer/reference-context.d.ts.map +1 -1
  51. package/dist/indexer/reference-context.js +2 -2
  52. package/dist/indexer/reference-context.js.map +1 -1
  53. package/dist/languages/filePrep.d.ts +11 -6
  54. package/dist/languages/filePrep.d.ts.map +1 -1
  55. package/dist/languages/filePrep.js +1 -1
  56. package/dist/languages/filePrep.js.map +1 -1
  57. package/dist/languages.d.ts +16 -0
  58. package/dist/languages.d.ts.map +1 -1
  59. package/dist/languages.js +41 -8
  60. package/dist/languages.js.map +1 -1
  61. package/dist/review/risk.js +2 -2
  62. package/dist/review/risk.js.map +1 -1
  63. package/dist/sql/sourceGraph.d.ts.map +1 -1
  64. package/dist/sql/sourceGraph.js +2 -2
  65. package/dist/sql/sourceGraph.js.map +1 -1
  66. package/dist/util/lazySymbols.js +2 -2
  67. package/dist/util/lazySymbols.js.map +1 -1
  68. package/dist/util/specifiers.d.ts +12 -0
  69. package/dist/util/specifiers.d.ts.map +1 -1
  70. package/dist/util/specifiers.js +271 -0
  71. package/dist/util/specifiers.js.map +1 -1
  72. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -4584,7 +4584,9 @@ __export(languages_exports, {
4584
4584
  languageExtensionPatterns: () => languageExtensionPatterns,
4585
4585
  normalizeLanguageExtensions: () => normalizeLanguageExtensions,
4586
4586
  supportById: () => supportById,
4587
- supportForFile: () => supportForFile
4587
+ supportForFile: () => supportForFile,
4588
+ supportForFileWithSource: () => supportForFileWithSource,
4589
+ supportForFileWithoutHeaderSample: () => supportForFileWithoutHeaderSample
4588
4590
  });
4589
4591
  import fs5 from "node:fs";
4590
4592
  import path4 from "node:path";
@@ -4628,6 +4630,8 @@ function languageExtensionPatterns(extensions) {
4628
4630
  return Object.keys(normalizeLanguageExtensions(extensions) ?? {}).map(caseInsensitiveExtensionPattern);
4629
4631
  }
4630
4632
  function mappedSupportForFile(filename, extensionMap) {
4633
+ if (!extensionMap)
4634
+ return void 0;
4631
4635
  const mappings = Object.entries(normalizeLanguageExtensions(extensionMap) ?? {}).sort((left, right) => right[0].length - left[0].length || left[0].localeCompare(right[0]));
4632
4636
  const lowerFilename = filename.toLowerCase();
4633
4637
  for (const [extension, languageId] of mappings) {
@@ -4637,19 +4641,36 @@ function mappedSupportForFile(filename, extensionMap) {
4637
4641
  }
4638
4642
  return void 0;
4639
4643
  }
4640
- function supportForFile(filename, extensionMap) {
4641
- const mapped = extensionMap ? mappedSupportForFile(filename, extensionMap) : void 0;
4644
+ function supportForFileWithoutHeaderSample(filename, extensionMap) {
4645
+ const mapped = mappedSupportForFile(filename, extensionMap);
4642
4646
  if (mapped)
4643
4647
  return mapped;
4644
4648
  const ext = path4.extname(filename).toLowerCase();
4645
- if (ext === ".h") {
4646
- const sample = readFileSample(filename);
4647
- if (sample && isLikelyCppHeader(sample))
4648
- return CPP_SUPPORT;
4649
- return C_SUPPORT;
4650
- }
4651
4649
  return LANGUAGE_SUPPORTS.find((s) => s.matchExts.includes(ext));
4652
4650
  }
4651
+ function supportForFile(filename, extensionMap) {
4652
+ if (path4.extname(filename).toLowerCase() !== ".h") {
4653
+ return supportForFileWithoutHeaderSample(filename, extensionMap);
4654
+ }
4655
+ const mapped = mappedSupportForFile(filename, extensionMap);
4656
+ if (mapped)
4657
+ return mapped;
4658
+ const sample = readFileSample(filename);
4659
+ if (sample && isLikelyCppHeader(sample))
4660
+ return CPP_SUPPORT;
4661
+ return C_SUPPORT;
4662
+ }
4663
+ function supportForFileWithSource(filename, source, extensionMap) {
4664
+ if (path4.extname(filename).toLowerCase() !== ".h") {
4665
+ return supportForFileWithoutHeaderSample(filename, extensionMap);
4666
+ }
4667
+ const mapped = mappedSupportForFile(filename, extensionMap);
4668
+ if (mapped)
4669
+ return mapped;
4670
+ if (isLikelyCppHeader(source.slice(0, HEADER_SAMPLE_SIZE)))
4671
+ return CPP_SUPPORT;
4672
+ return C_SUPPORT;
4673
+ }
4653
4674
  function supportById(id) {
4654
4675
  return LANGUAGE_SUPPORTS.find((s) => s.id === id);
4655
4676
  }
@@ -19547,7 +19568,7 @@ async function prepareSourceInput(file2, opts) {
19547
19568
  const rawSource2 = opts?.source ?? await fsp14.readFile(file2, "utf8");
19548
19569
  return prepareSFCSourceInput(rawSource2, framework);
19549
19570
  }
19550
- const sup = supportForFile(file2, opts?.languageExtensions);
19571
+ const sup = opts?.support ?? supportForFile(file2, opts?.languageExtensions);
19551
19572
  if (!sup)
19552
19573
  throw new UnsupportedParserInputError(file2);
19553
19574
  const rawSource = opts?.source ?? await fsp14.readFile(file2, "utf8");
@@ -21827,6 +21848,243 @@ function extractJsTsDynamicSpecifiers(source, fromFile, projectRoot) {
21827
21848
  }
21828
21849
  return out;
21829
21850
  }
21851
+ function maskPythonString(source, mask, start) {
21852
+ const quote = source[start];
21853
+ const triple = source[start + 1] === quote && source[start + 2] === quote;
21854
+ const delimiterLength = triple ? 3 : 1;
21855
+ for (let offset = 0; offset < delimiterLength; offset += 1) {
21856
+ mask[start + offset] = 1;
21857
+ }
21858
+ let index = start + delimiterLength;
21859
+ while (index < source.length) {
21860
+ const ch = source[index];
21861
+ if (!triple && (ch === "\n" || ch === "\r"))
21862
+ return index;
21863
+ mask[index] = 1;
21864
+ if (ch === "\\") {
21865
+ const nextIndex = index + 1;
21866
+ if (nextIndex < source.length)
21867
+ mask[nextIndex] = 1;
21868
+ index += 2;
21869
+ continue;
21870
+ }
21871
+ if (ch === quote) {
21872
+ if (!triple)
21873
+ return index + 1;
21874
+ if (source[index + 1] === quote && source[index + 2] === quote) {
21875
+ mask[index + 1] = 1;
21876
+ mask[index + 2] = 1;
21877
+ return index + delimiterLength;
21878
+ }
21879
+ }
21880
+ index += 1;
21881
+ }
21882
+ return source.length;
21883
+ }
21884
+ function buildPythonNonCodeMask(source) {
21885
+ if (!source.includes("#") && !source.includes("'") && !source.includes('"'))
21886
+ return void 0;
21887
+ const mask = new Uint8Array(source.length);
21888
+ for (let index = 0; index < source.length; index += 1) {
21889
+ const ch = source[index];
21890
+ if (ch === "#") {
21891
+ while (index < source.length && source[index] !== "\n" && source[index] !== "\r") {
21892
+ mask[index] = 1;
21893
+ index += 1;
21894
+ }
21895
+ index -= 1;
21896
+ continue;
21897
+ }
21898
+ if (ch === "'" || ch === '"') {
21899
+ index = maskPythonString(source, mask, index) - 1;
21900
+ }
21901
+ }
21902
+ return mask;
21903
+ }
21904
+ function decodePythonStringContent(content, prefix) {
21905
+ if (prefix.includes("r"))
21906
+ return content;
21907
+ let decoded = "";
21908
+ for (let index = 0; index < content.length; index += 1) {
21909
+ const ch = content[index];
21910
+ if (ch !== "\\") {
21911
+ decoded += ch;
21912
+ continue;
21913
+ }
21914
+ index += 1;
21915
+ const escape2 = content[index];
21916
+ if (escape2 === void 0)
21917
+ return null;
21918
+ const simpleEscape = PYTHON_SIMPLE_STRING_ESCAPES[escape2];
21919
+ if (simpleEscape !== void 0) {
21920
+ decoded += simpleEscape;
21921
+ continue;
21922
+ }
21923
+ if (escape2 === "\n")
21924
+ continue;
21925
+ if (escape2 === "\r") {
21926
+ if (content[index + 1] === "\n")
21927
+ index += 1;
21928
+ continue;
21929
+ }
21930
+ let hexLength = 0;
21931
+ if (escape2 === "x")
21932
+ hexLength = 2;
21933
+ else if (escape2 === "u")
21934
+ hexLength = 4;
21935
+ else if (escape2 === "U")
21936
+ hexLength = 8;
21937
+ if (hexLength) {
21938
+ const digits = content.slice(index + 1, index + 1 + hexLength);
21939
+ if (digits.length !== hexLength || !/^[0-9a-fA-F]+$/.test(digits))
21940
+ return null;
21941
+ const codePoint = Number.parseInt(digits, 16);
21942
+ if (codePoint > 1114111)
21943
+ return null;
21944
+ decoded += String.fromCodePoint(codePoint);
21945
+ index += hexLength;
21946
+ continue;
21947
+ }
21948
+ if (escape2 >= "0" && escape2 <= "7") {
21949
+ let end = index + 1;
21950
+ while (end < content.length && end - index < 3) {
21951
+ const digit = content[end];
21952
+ if (digit < "0" || digit > "7")
21953
+ break;
21954
+ end += 1;
21955
+ }
21956
+ decoded += String.fromCodePoint(Number.parseInt(content.slice(index, end), 8));
21957
+ index = end - 1;
21958
+ continue;
21959
+ }
21960
+ decoded += `\\${escape2}`;
21961
+ }
21962
+ return decoded;
21963
+ }
21964
+ function parsePythonStaticStringLiteral(source, start) {
21965
+ let quoteIndex = start;
21966
+ let prefixLength = 0;
21967
+ while (prefixLength < 2) {
21968
+ const prefixCharacter = source[quoteIndex];
21969
+ if (!prefixCharacter || !"rRuUfF".includes(prefixCharacter))
21970
+ break;
21971
+ quoteIndex += 1;
21972
+ prefixLength += 1;
21973
+ }
21974
+ const prefix = source.slice(start, quoteIndex).toLowerCase();
21975
+ if (!["", "r", "u", "f", "fr", "rf"].includes(prefix))
21976
+ return null;
21977
+ const quote = source[quoteIndex];
21978
+ if (quote !== "'" && quote !== '"')
21979
+ return null;
21980
+ const triple = source[quoteIndex + 1] === quote && source[quoteIndex + 2] === quote;
21981
+ const delimiterLength = triple ? 3 : 1;
21982
+ const contentStart = quoteIndex + delimiterLength;
21983
+ for (let index = contentStart; index < source.length; index += 1) {
21984
+ const ch = source[index];
21985
+ if (!triple && (ch === "\n" || ch === "\r"))
21986
+ return null;
21987
+ if (ch === "\\") {
21988
+ index += 1;
21989
+ continue;
21990
+ }
21991
+ if (ch !== quote)
21992
+ continue;
21993
+ if (triple && (source[index + 1] !== quote || source[index + 2] !== quote))
21994
+ continue;
21995
+ const value = decodePythonStringContent(source.slice(contentStart, index), prefix);
21996
+ if (value === null)
21997
+ return null;
21998
+ return { value, end: index + delimiterLength };
21999
+ }
22000
+ return null;
22001
+ }
22002
+ function skipPythonExpressionTrivia(source, start) {
22003
+ let index = start;
22004
+ while (index < source.length) {
22005
+ while (index < source.length && /\s/.test(source[index]))
22006
+ index += 1;
22007
+ if (source[index] !== "#")
22008
+ break;
22009
+ while (index < source.length && source[index] !== "\n" && source[index] !== "\r")
22010
+ index += 1;
22011
+ }
22012
+ return index;
22013
+ }
22014
+ function parsePythonStaticStringExpression(source, start) {
22015
+ let index = skipPythonExpressionTrivia(source, start);
22016
+ let value = "";
22017
+ let literalCount = 0;
22018
+ while (true) {
22019
+ const literal2 = parsePythonStaticStringLiteral(source, index);
22020
+ if (!literal2)
22021
+ break;
22022
+ value += literal2.value;
22023
+ literalCount += 1;
22024
+ index = skipPythonExpressionTrivia(source, literal2.end);
22025
+ }
22026
+ if (!literalCount || source[index] !== "," && source[index] !== ")")
22027
+ return null;
22028
+ return value;
22029
+ }
22030
+ function collectPythonDynamicImportAliases(source) {
22031
+ const importlibAliases = /* @__PURE__ */ new Set(["importlib"]);
22032
+ const importModuleAliases = /* @__PURE__ */ new Set();
22033
+ const cleaned = stripPythonCommentsAndStrings(source);
22034
+ for (const match of cleaned.matchAll(/^\s*import\s+([^\r\n;]+)/gmu)) {
22035
+ for (const rawClause of (match[1] ?? "").split(",")) {
22036
+ const clause = rawClause.trim();
22037
+ const parsed = PYTHON_IMPORTLIB_ALIAS_PATTERN.exec(clause);
22038
+ if (parsed)
22039
+ importlibAliases.add(parsed[1] ?? "importlib");
22040
+ }
22041
+ }
22042
+ for (const match of cleaned.matchAll(PYTHON_FROM_IMPORTLIB_PATTERN)) {
22043
+ const importList = match[1] ?? match[2] ?? "";
22044
+ for (const rawClause of importList.split(",")) {
22045
+ const clause = rawClause.trim();
22046
+ const parsed = PYTHON_IMPORT_MODULE_ALIAS_PATTERN.exec(clause);
22047
+ if (parsed)
22048
+ importModuleAliases.add(parsed[1] ?? "import_module");
22049
+ }
22050
+ }
22051
+ return { importlibAliases, importModuleAliases };
22052
+ }
22053
+ function extractPythonDynamicSpecifiers(source) {
22054
+ const out = [];
22055
+ try {
22056
+ const mask = buildPythonNonCodeMask(source);
22057
+ const { importlibAliases, importModuleAliases } = collectPythonDynamicImportAliases(source);
22058
+ const seen = /* @__PURE__ */ new Set();
22059
+ for (const match of source.matchAll(PYTHON_DYNAMIC_CALL_PREFIX_PATTERN)) {
22060
+ if (!matchStartsInCode(mask, match))
22061
+ continue;
22062
+ const receiver = match[1] ?? "";
22063
+ const member = match[2];
22064
+ const isBuiltinImport = !member && receiver === "__import__";
22065
+ const isImportlibCall = member === "import_module" && importlibAliases.has(receiver);
22066
+ const isImportedFunctionCall = !member && importModuleAliases.has(receiver);
22067
+ if (!isBuiltinImport && !isImportlibCall && !isImportedFunctionCall)
22068
+ continue;
22069
+ const argumentStart = (match.index ?? 0) + (match[0]?.length ?? 0);
22070
+ const spec = parsePythonStaticStringExpression(source, argumentStart);
22071
+ if (!spec || !PYTHON_DYNAMIC_MODULE_PATTERN.test(spec) || seen.has(spec))
22072
+ continue;
22073
+ if (isBuiltinImport && spec.startsWith("."))
22074
+ continue;
22075
+ seen.add(spec);
22076
+ out.push({ spec, resolved: "heuristic", confidence: 0.7 });
22077
+ }
22078
+ } catch {
22079
+ }
22080
+ return out;
22081
+ }
22082
+ function extractDynamicImportSpecifiers(languageId, source, fromFile, projectRoot) {
22083
+ const extractor = DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS[languageId];
22084
+ if (!extractor)
22085
+ return [];
22086
+ return extractor(source, fromFile, projectRoot);
22087
+ }
21830
22088
  function extractPythonSpecifiers(source) {
21831
22089
  const out = [];
21832
22090
  try {
@@ -21841,7 +22099,7 @@ function extractPythonSpecifiers(source) {
21841
22099
  }
21842
22100
  return out;
21843
22101
  }
21844
- var PYTHON_DOTTED_NAME_SOURCE;
22102
+ var PYTHON_DOTTED_NAME_SOURCE, PYTHON_IMPORTLIB_ALIAS_PATTERN, PYTHON_IMPORT_MODULE_ALIAS_PATTERN, PYTHON_DYNAMIC_CALL_PREFIX_PATTERN, PYTHON_DYNAMIC_MODULE_PATTERN, PYTHON_FROM_IMPORTLIB_PATTERN, PYTHON_SIMPLE_STRING_ESCAPES, DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS;
21845
22103
  var init_specifiers = __esm({
21846
22104
  "dist/util/specifiers.js"() {
21847
22105
  "use strict";
@@ -21849,6 +22107,28 @@ var init_specifiers = __esm({
21849
22107
  init_identifiers();
21850
22108
  init_paths();
21851
22109
  PYTHON_DOTTED_NAME_SOURCE = String.raw`${PYTHON_IDENTIFIER_SOURCE}(?:\.${PYTHON_IDENTIFIER_SOURCE})*`;
22110
+ PYTHON_IMPORTLIB_ALIAS_PATTERN = new RegExp(String.raw`^importlib(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
22111
+ PYTHON_IMPORT_MODULE_ALIAS_PATTERN = new RegExp(String.raw`^import_module(?:\s+as\s+(${PYTHON_IDENTIFIER_SOURCE}))?$`, "u");
22112
+ PYTHON_DYNAMIC_CALL_PREFIX_PATTERN = new RegExp(String.raw`(?<![._\p{XID_Continue}])(${PYTHON_IDENTIFIER_SOURCE})(?:\s*\.\s*(${PYTHON_IDENTIFIER_SOURCE}))?\s*\(\s*(?:name\s*=\s*)?`, "gmu");
22113
+ PYTHON_DYNAMIC_MODULE_PATTERN = new RegExp(String.raw`^\.*${PYTHON_DOTTED_NAME_SOURCE}$`, "u");
22114
+ PYTHON_FROM_IMPORTLIB_PATTERN = /^\s*from\s+importlib\s+import\s+(?:\(([\s\S]*?)\)|([^\r\n;]+))/gmu;
22115
+ PYTHON_SIMPLE_STRING_ESCAPES = {
22116
+ "\\": "\\",
22117
+ "'": "'",
22118
+ '"': '"',
22119
+ a: "\x07",
22120
+ b: "\b",
22121
+ f: "\f",
22122
+ n: "\n",
22123
+ r: "\r",
22124
+ t: " ",
22125
+ v: "\v"
22126
+ };
22127
+ DYNAMIC_IMPORT_SPECIFIER_EXTRACTORS = {
22128
+ js: extractJsTsDynamicSpecifiers,
22129
+ ts: extractJsTsDynamicSpecifiers,
22130
+ python: extractPythonDynamicSpecifiers
22131
+ };
21852
22132
  }
21853
22133
  });
21854
22134
 
@@ -25267,7 +25547,7 @@ var init_extractFacts = __esm({
25267
25547
  import crypto2 from "node:crypto";
25268
25548
  import fsp16 from "node:fs/promises";
25269
25549
  function isSqlFile(filePath, languageExtensions) {
25270
- return supportForFile(filePath, languageExtensions)?.id === "sql";
25550
+ return supportForFileWithoutHeaderSample(filePath, languageExtensions)?.id === "sql";
25271
25551
  }
25272
25552
  function sqlCorpusSignature(sqlFiles2, fileSignatures) {
25273
25553
  if (!sqlFiles2.length || !fileSignatures)
@@ -25466,6 +25746,17 @@ var init_sourceGraph = __esm({
25466
25746
  });
25467
25747
 
25468
25748
  // dist/graph-edge-collector.js
25749
+ function appendMissingSpecifiers(target, incoming) {
25750
+ if (!incoming.length)
25751
+ return;
25752
+ const existing = new Set(target.map((entry) => entry.spec));
25753
+ for (const entry of incoming) {
25754
+ if (existing.has(entry.spec))
25755
+ continue;
25756
+ existing.add(entry.spec);
25757
+ target.push(entry);
25758
+ }
25759
+ }
25469
25760
  function deduplicateEdges(edges, rawIsIdentity = false) {
25470
25761
  const deduplicated = /* @__PURE__ */ new Map();
25471
25762
  for (const edge of edges) {
@@ -25505,7 +25796,7 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25505
25796
  const sigEntry = opts.fileSignature;
25506
25797
  const sig = sigEntry?.sig;
25507
25798
  const gitSig = sigEntry?.gitSig;
25508
- const sqlFile = supportForFile(normalizedFile, opts.languageExtensions)?.id === "sql";
25799
+ const sqlFile = supportForFileWithoutHeaderSample(normalizedFile, opts.languageExtensions)?.id === "sql";
25509
25800
  const emitCacheEntry = (edges2) => {
25510
25801
  if (!sig || !opts.onFileEdges)
25511
25802
  return;
@@ -25572,17 +25863,8 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25572
25863
  ...opts.native ? { native: opts.native } : {},
25573
25864
  ...opts.logLevel ? { logLevel: opts.logLevel } : {}
25574
25865
  });
25575
- if ((sup.id === "ts" || sup.id === "js") && opts.dynamicImportHeuristics) {
25576
- const dynamicSpecs = extractJsTsDynamicSpecifiers(src, normalizedFile, projectRoot);
25577
- if (dynamicSpecs.length) {
25578
- const existing = new Set(specs.map((entry) => entry.spec));
25579
- for (const entry of dynamicSpecs) {
25580
- if (existing.has(entry.spec))
25581
- continue;
25582
- existing.add(entry.spec);
25583
- specs.push(entry);
25584
- }
25585
- }
25866
+ if (opts.dynamicImportHeuristics) {
25867
+ appendMissingSpecifiers(specs, extractDynamicImportSpecifiers(sup.id, src, normalizedFile, projectRoot));
25586
25868
  }
25587
25869
  const specSources = specs.map((entry) => ({ entry, support: sup }));
25588
25870
  for (const block of embeddedBlocks) {
@@ -25594,6 +25876,9 @@ async function collectEdgesForFile(file2, projectRoot, workspaceConfig, opts) {
25594
25876
  ...opts.native ? { native: opts.native } : {},
25595
25877
  ...opts.logLevel ? { logLevel: opts.logLevel } : {}
25596
25878
  });
25879
+ if (opts.dynamicImportHeuristics) {
25880
+ appendMissingSpecifiers(blockSpecs, extractDynamicImportSpecifiers(block.sup.id, block.source, normalizedFile, projectRoot));
25881
+ }
25597
25882
  for (const entry of blockSpecs) {
25598
25883
  specSources.push({ entry, support: block.sup });
25599
25884
  }
@@ -25672,7 +25957,7 @@ function canReuseSqlEdgeCache(file2, sqlCorpusSig, fileSignatures, cachedFileEdg
25672
25957
  async function collectGraph(projectRoot, files, opts) {
25673
25958
  const normalizedFiles = files.map(normalizePath);
25674
25959
  const normalizedAllFiles = (opts?.allFiles ?? files).map(normalizePath);
25675
- const isSqlFile4 = (file2) => supportForFile(file2, opts?.languageExtensions)?.id === "sql";
25960
+ const isSqlFile4 = (file2) => supportForFileWithoutHeaderSample(file2, opts?.languageExtensions)?.id === "sql";
25676
25961
  const hasExplicitReplace = !!opts?.replaceFiles;
25677
25962
  const requestedReplaceSet = hasExplicitReplace ? new Set(Array.from(opts.replaceFiles ?? [], (file2) => normalizePath(file2))) : new Set(normalizedFiles);
25678
25963
  const sqlFiles2 = Array.from(new Set(normalizedAllFiles.filter(isSqlFile4))).sort((left, right) => left.localeCompare(right));
@@ -26336,8 +26621,12 @@ function parsePreparedFileContext(context) {
26336
26621
  }
26337
26622
  throw new Error(`Failed to reconstruct syntax tree for ${context.file}`);
26338
26623
  }
26339
- async function prepareFileForIndexing(file2, native, languageExtensions, source) {
26340
- const prep = await prepareSourceInput(file2, { languageExtensions, ...source !== void 0 ? { source } : {} });
26624
+ async function prepareFileForIndexing(file2, native, languageExtensions, source, support) {
26625
+ const prep = await prepareSourceInput(file2, {
26626
+ languageExtensions,
26627
+ ...source !== void 0 ? { source } : {},
26628
+ ...support ? { support } : {}
26629
+ });
26341
26630
  if (isGraphOnlyLanguage(prep.sup.id)) {
26342
26631
  return {
26343
26632
  file: file2,
@@ -32499,7 +32788,7 @@ async function cacheSignatureForFile(file2, sigInfo, opts) {
32499
32788
  async function buildBloomFilterForFile(file2, opts) {
32500
32789
  try {
32501
32790
  const source = await fsp18.readFile(file2, "utf8");
32502
- const support = supportForFile(file2, opts?.languageExtensions);
32791
+ const support = supportForFileWithoutHeaderSample(file2, opts?.languageExtensions);
32503
32792
  if (!support)
32504
32793
  return null;
32505
32794
  return buildBloomFilterFromSource(source, support);
@@ -33267,8 +33556,13 @@ function winnowShingles(shingles, windowSize, maxFingerprints) {
33267
33556
  }
33268
33557
  return fingerprints;
33269
33558
  }
33270
- function languageForFile(filePath) {
33271
- const support = supportForFile(filePath);
33559
+ function isDuplicateCandidateFile(filePath) {
33560
+ if (supportForFileWithoutHeaderSample(filePath))
33561
+ return true;
33562
+ return !!textLanguageByExtension[path39.extname(filePath).toLowerCase()];
33563
+ }
33564
+ function languageForFile(filePath, source) {
33565
+ const support = supportForFileWithSource(filePath, source);
33272
33566
  if (support) {
33273
33567
  return { id: support.id, textOnly: false };
33274
33568
  }
@@ -33443,7 +33737,7 @@ async function getDuplicateAstContext(index, file2, source, cache) {
33443
33737
  return context;
33444
33738
  }
33445
33739
  try {
33446
- const prepared = await prepareSourceInput(file2, { source });
33740
+ const prepared = await prepareSourceInput(file2, { source, support: supportForFileWithSource(file2, source) });
33447
33741
  const attempt = attemptParsePreparedFileContext({
33448
33742
  file: file2,
33449
33743
  source: prepared.source,
@@ -33610,11 +33904,11 @@ async function collectDuplicateUnits(index, options) {
33610
33904
  return { units, belowThresholdUnits, belowThresholdUnitsByFile };
33611
33905
  }
33612
33906
  async function buildDuplicateUnitsForFile(index, file2, projectRoot, minTokens, maxTokens, shingleSize, windowSize, astContextCache) {
33613
- const moduleIndex = index.byFile.get(fileIdentityKey(file2));
33614
- const language = languageForFile(file2);
33615
- if (!language)
33907
+ const fileKey = fileIdentityKey(file2);
33908
+ const moduleIndex = index.byFile.get(fileKey);
33909
+ if (!isDuplicateCandidateFile(file2))
33616
33910
  return [];
33617
- let source = index.parsed?.get(fileIdentityKey(file2))?.source;
33911
+ let source = index.parsed?.get(fileKey)?.source;
33618
33912
  if (source === void 0) {
33619
33913
  try {
33620
33914
  source = await fsp19.readFile(file2, "utf8");
@@ -33622,6 +33916,9 @@ async function buildDuplicateUnitsForFile(index, file2, projectRoot, minTokens,
33622
33916
  return [];
33623
33917
  }
33624
33918
  }
33919
+ const language = languageForFile(file2, source);
33920
+ if (!language)
33921
+ return [];
33625
33922
  const astContext = language.textOnly ? void 0 : await getDuplicateAstContext(index, file2, source, astContextCache);
33626
33923
  const { chunks, symbolChunks } = makeDuplicateChunksWithSymbols(file2, language.id, language.textOnly, source, minTokens, maxTokens);
33627
33924
  const symbolUnits = (moduleIndex?.locals ?? []).map((symbol2) => {
@@ -51174,7 +51471,7 @@ function moduleNameLookup(index, file2) {
51174
51471
  if (!lookups) {
51175
51472
  lookups = /* @__PURE__ */ new Map();
51176
51473
  for (const moduleEntry of index.byFile.values()) {
51177
- const normalizeIdentifier = supportForFile(moduleEntry.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51474
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(moduleEntry.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51178
51475
  const localExports = /* @__PURE__ */ new Map();
51179
51476
  const namespaceReexports = /* @__PURE__ */ new Map();
51180
51477
  const reexports = /* @__PURE__ */ new Map();
@@ -51219,7 +51516,7 @@ function sameSymbolDef(index, left, right) {
51219
51516
  if (fileIdentityKey(left.file) !== fileIdentityKey(right.file) || left.kind !== right.kind) {
51220
51517
  return false;
51221
51518
  }
51222
- const normalizeIdentifier = supportForFile(left.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51519
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(left.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
51223
51520
  if (normalizeIdentifier(left.localName) !== normalizeIdentifier(right.localName)) {
51224
51521
  return false;
51225
51522
  }
@@ -51249,64 +51546,68 @@ function packageNameCacheFor(index) {
51249
51546
  }
51250
51547
  return caches;
51251
51548
  }
51549
+ function packageDeclarationSource(index, filePath, fileKey) {
51550
+ const retained = index.parsed?.get(fileKey)?.source;
51551
+ if (retained !== void 0)
51552
+ return retained;
51553
+ try {
51554
+ return fs20.readFileSync(filePath, "utf8");
51555
+ } catch {
51556
+ return null;
51557
+ }
51558
+ }
51252
51559
  function readGoPackageName(index, filePath) {
51253
51560
  const cache = packageNameCacheFor(index).go;
51254
51561
  const key = fileIdentityKey(filePath);
51255
51562
  const cached2 = cache.get(key);
51256
51563
  if (cached2 !== void 0)
51257
51564
  return cached2;
51258
- try {
51259
- const source = fs20.readFileSync(filePath, "utf8");
51260
- const match = GO_PACKAGE_PATTERN.exec(source);
51261
- const packageName = match?.[1] ?? null;
51262
- cache.set(key, packageName);
51263
- return packageName;
51264
- } catch {
51565
+ const source = packageDeclarationSource(index, filePath, key);
51566
+ if (source === null) {
51265
51567
  cache.set(key, null);
51266
51568
  return null;
51267
51569
  }
51570
+ const packageName = GO_PACKAGE_PATTERN.exec(source)?.[1] ?? null;
51571
+ cache.set(key, packageName);
51572
+ return packageName;
51268
51573
  }
51269
51574
  function resolveGoPackageExport(index, file2, exportedName) {
51270
- try {
51271
- const support = supportForFile(file2, index.languageExtensions);
51272
- if (!support || support.id !== "go")
51273
- return null;
51274
- const directory = packageDirectoryLookup(index, "go").get(fileIdentityKey(path42.dirname(file2)));
51275
- if (!directory)
51276
- return null;
51277
- const sourcePackage = readGoPackageName(index, file2);
51278
- const candidates = sourcePackage ? directory.byName.get(sourcePackage) ?? [] : directory.all;
51279
- const matches = [];
51280
- for (const moduleEntry of candidates) {
51281
- const names = moduleNameLookup(index, moduleEntry.file);
51282
- if (!names)
51283
- continue;
51284
- for (const target of names.localExports.get(names.normalizeIdentifier(exportedName)) ?? []) {
51285
- if (!matches.some((candidate) => sameSymbolDef(index, candidate, target))) {
51286
- matches.push(target);
51287
- }
51575
+ if (supportForFileWithoutHeaderSample(file2, index.languageExtensions)?.id !== "go")
51576
+ return null;
51577
+ const directory = packageDirectoryLookup(index, "go").get(fileIdentityKey(path42.dirname(file2)));
51578
+ if (!directory)
51579
+ return null;
51580
+ const sourcePackage = readGoPackageName(index, file2);
51581
+ const candidates = sourcePackage ? directory.byName.get(sourcePackage) ?? [] : directory.all;
51582
+ const matches = [];
51583
+ for (const moduleEntry of candidates) {
51584
+ const names = moduleNameLookup(index, moduleEntry.file);
51585
+ if (!names)
51586
+ continue;
51587
+ for (const target of names.localExports.get(names.normalizeIdentifier(exportedName)) ?? []) {
51588
+ if (!matches.some((candidate) => sameSymbolDef(index, candidate, target))) {
51589
+ matches.push(target);
51288
51590
  }
51289
51591
  }
51290
- return matches.length === 1 ? matches[0] ?? null : null;
51291
- } catch {
51292
51592
  }
51293
- return null;
51593
+ return matches.length === 1 ? matches[0] ?? null : null;
51294
51594
  }
51295
51595
  function readPackageNameForLanguage(index, filePath, languageId) {
51296
51596
  const cache = packageNameCacheFor(index).jvm;
51297
- const key = `${languageId}::${fileIdentityKey(filePath)}`;
51597
+ const fileKey = fileIdentityKey(filePath);
51598
+ const key = `${languageId}::${fileKey}`;
51298
51599
  const cached2 = cache.get(key);
51299
51600
  if (cached2 !== void 0)
51300
51601
  return cached2;
51301
- try {
51302
- const source = fs20.readFileSync(filePath, "utf8");
51303
- const packageName = languageId === "kotlin" ? KOTLIN_PACKAGE_NAME_PATTERN.exec(source)?.[1] ?? null : JAVA_PACKAGE_NAME_PATTERN.exec(source)?.[1] ?? null;
51304
- cache.set(key, packageName);
51305
- return packageName;
51306
- } catch {
51602
+ const source = packageDeclarationSource(index, filePath, fileKey);
51603
+ if (source === null) {
51307
51604
  cache.set(key, null);
51308
51605
  return null;
51309
51606
  }
51607
+ const pattern = languageId === "kotlin" ? KOTLIN_PACKAGE_NAME_PATTERN : JAVA_PACKAGE_NAME_PATTERN;
51608
+ const packageName = pattern.exec(source)?.[1] ?? null;
51609
+ cache.set(key, packageName);
51610
+ return packageName;
51310
51611
  }
51311
51612
  function packageDirectoryLookup(index, languageId) {
51312
51613
  let byLanguage = packageDirectoryLookups.get(index);
@@ -51326,6 +51627,9 @@ function packageDirectoryLookup(index, languageId) {
51326
51627
  directories.set(directoryKey, directory);
51327
51628
  }
51328
51629
  directory.all.push(moduleEntry);
51630
+ const moduleLanguageId = supportForFileWithoutHeaderSample(moduleEntry.file, index.languageExtensions)?.id;
51631
+ if (!moduleLanguageId || !PACKAGE_DECLARING_LANGUAGE_IDS[languageId].has(moduleLanguageId))
51632
+ continue;
51329
51633
  const packageName = languageId === "go" ? readGoPackageName(index, moduleEntry.file) : readPackageNameForLanguage(index, moduleEntry.file, languageId);
51330
51634
  if (!packageName)
51331
51635
  continue;
@@ -51552,30 +51856,23 @@ function resolveImported(index, imp, exportedName) {
51552
51856
  return hit.def;
51553
51857
  if (hit?.kind === "namespace")
51554
51858
  return { namespace: hit.file };
51555
- try {
51556
- const support = supportForFile(targetFile);
51557
- if (support?.id === "java" || support?.id === "kotlin") {
51558
- const siblingHit = resolveSiblingPackageExport(index, targetFile, exportedName, support.id);
51559
- if (siblingHit?.kind === "resolved")
51560
- return siblingHit.def;
51561
- if (siblingHit?.kind === "namespace") {
51562
- return { namespace: siblingHit.file };
51563
- }
51859
+ const support = supportForFileWithoutHeaderSample(targetFile, index.languageExtensions);
51860
+ if (support?.id === "java" || support?.id === "kotlin") {
51861
+ const siblingHit = resolveSiblingPackageExport(index, targetFile, exportedName, support.id);
51862
+ if (siblingHit?.kind === "resolved")
51863
+ return siblingHit.def;
51864
+ if (siblingHit?.kind === "namespace") {
51865
+ return { namespace: siblingHit.file };
51564
51866
  }
51565
- } catch {
51566
51867
  }
51567
- try {
51568
- const support = supportForFile(targetFile);
51569
- if (support?.id === "python") {
51570
- const submodule = resolvePythonSubmodule(targetFile, exportedName);
51571
- if (submodule)
51572
- return { namespace: submodule };
51573
- }
51574
- } catch {
51868
+ if (support?.id === "python") {
51869
+ const submodule = resolvePythonSubmodule(targetFile, exportedName);
51870
+ if (submodule)
51871
+ return { namespace: submodule };
51575
51872
  }
51576
51873
  return null;
51577
51874
  }
51578
- var GO_PACKAGE_PATTERN, JAVA_PACKAGE_NAME_PATTERN, KOTLIN_PACKAGE_NAME_PATTERN, moduleNameLookups, packageDirectoryLookups, packageNameCaches;
51875
+ var GO_PACKAGE_PATTERN, JAVA_PACKAGE_NAME_PATTERN, KOTLIN_PACKAGE_NAME_PATTERN, PACKAGE_DECLARING_LANGUAGE_IDS, moduleNameLookups, packageDirectoryLookups, packageNameCaches;
51579
51876
  var init_navigation_resolve = __esm({
51580
51877
  "dist/indexer/navigation-resolve.js"() {
51581
51878
  "use strict";
@@ -51586,6 +51883,11 @@ var init_navigation_resolve = __esm({
51586
51883
  GO_PACKAGE_PATTERN = new RegExp(String.raw`^\s*package\s+(${GO_IDENTIFIER_SOURCE})`, "mu");
51587
51884
  JAVA_PACKAGE_NAME_PATTERN = new RegExp(String.raw`^\s*package\s+(${JAVA_IDENTIFIER_SOURCE}(?:\.${JAVA_IDENTIFIER_SOURCE})*)\s*;`, "mu");
51588
51885
  KOTLIN_PACKAGE_NAME_PATTERN = new RegExp(String.raw`^\s*package\s+(${KOTLIN_IDENTIFIER_SOURCE}(?:\.${KOTLIN_IDENTIFIER_SOURCE})*)`, "mu");
51886
+ PACKAGE_DECLARING_LANGUAGE_IDS = {
51887
+ go: /* @__PURE__ */ new Set(["go"]),
51888
+ java: /* @__PURE__ */ new Set(["java", "kotlin"]),
51889
+ kotlin: /* @__PURE__ */ new Set(["java", "kotlin"])
51890
+ };
51589
51891
  moduleNameLookups = /* @__PURE__ */ new WeakMap();
51590
51892
  packageDirectoryLookups = /* @__PURE__ */ new WeakMap();
51591
51893
  packageNameCaches = /* @__PURE__ */ new WeakMap();
@@ -54643,7 +54945,7 @@ function isNativeWorkerEligibleFile(filePath, support) {
54643
54945
  function countNativeWorkerEligibleFiles(files, languageExtensions) {
54644
54946
  let count = 0;
54645
54947
  for (const file2 of files) {
54646
- if (isNativeWorkerEligibleFile(file2, supportForFile(file2, languageExtensions)))
54948
+ if (isNativeWorkerEligibleFile(file2, supportForFileWithoutHeaderSample(file2, languageExtensions)))
54647
54949
  count++;
54648
54950
  }
54649
54951
  return count;
@@ -54778,10 +55080,10 @@ async function prepareFileContextForBuild(file2, support, opts, workerSetup, rep
54778
55080
  workerSetup.report.errors.push({ file: file2, message: stringifyUnknown(error51) });
54779
55081
  }
54780
55082
  }
54781
- prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source);
55083
+ prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source, support);
54782
55084
  }
54783
55085
  } else {
54784
- prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source);
55086
+ prepared = await prepareFileForIndexing(file2, opts?.native, opts?.languageExtensions, source, support);
54785
55087
  }
54786
55088
  recordPreparedNativeExecutionOutcome(report, prepared);
54787
55089
  return prepared;
@@ -55425,7 +55727,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55425
55727
  const sqlFiles2 = normalizedFiles.filter((file2) => {
55426
55728
  if (!languageExtensions)
55427
55729
  return path47.extname(file2).toLowerCase() === ".sql";
55428
- return supportForFile(file2, languageExtensions)?.id === "sql";
55730
+ return supportForFileWithoutHeaderSample(file2, languageExtensions)?.id === "sql";
55429
55731
  }).sort((left, right) => left.localeCompare(right));
55430
55732
  const fileSignatures = await prepareFileSignatures({
55431
55733
  projectRoot,
@@ -55443,7 +55745,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55443
55745
  return sqlFactCachePromise;
55444
55746
  };
55445
55747
  const shouldProvideSqlFactCache = (file2, sigInfo, cachedEdgesEntry) => {
55446
- if (supportForFile(file2, opts?.languageExtensions)?.id !== "sql")
55748
+ if (supportForFileWithoutHeaderSample(file2, opts?.languageExtensions)?.id !== "sql")
55447
55749
  return false;
55448
55750
  if (!cachedEdgesEntry || !sqlCorpusSig || cachedEdgesEntry.sqlCorpusSig !== sqlCorpusSig)
55449
55751
  return true;
@@ -64194,7 +64496,7 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
64194
64496
  return absoluteFile;
64195
64497
  }
64196
64498
  }));
64197
- const markdownFiles = Array.from(new Set(markdownFileCandidates)).filter((file2) => isFilePathWithinRoot(realRoot, file2)).filter((file2) => supportForFile(file2)?.id === "markdown");
64499
+ const markdownFiles = Array.from(new Set(markdownFileCandidates)).filter((file2) => isFilePathWithinRoot(realRoot, file2)).filter((file2) => supportForFileWithoutHeaderSample(file2)?.id === "markdown");
64198
64500
  const targetStatusByPath = /* @__PURE__ */ new Map();
64199
64501
  const anchorsByPath = /* @__PURE__ */ new Map();
64200
64502
  const failures = [];
@@ -64233,7 +64535,7 @@ async function checkMarkdownLinksInFiles(projectRoot, files) {
64233
64535
  failures.push(toFailure(realRoot, displayFile, occurrence, "outside_root", resolvedTarget));
64234
64536
  continue;
64235
64537
  }
64236
- if (!target.fragment || targetStatus.isDirectory || supportForFile(resolvedTarget)?.id !== "markdown")
64538
+ if (!target.fragment || targetStatus.isDirectory || supportForFileWithoutHeaderSample(resolvedTarget)?.id !== "markdown")
64237
64539
  continue;
64238
64540
  const anchors = await cachedMarkdownAnchors(targetStatus.realPath, anchorsByPath);
64239
64541
  if (!anchors.has(target.fragment)) {
@@ -65302,7 +65604,7 @@ var init_navigation_php = __esm({
65302
65604
  function sameDef(left, right, languageExtensions) {
65303
65605
  const leftIndex = left.range.start.index ?? 0;
65304
65606
  const rightIndex = right.range.start.index ?? 0;
65305
- const normalizeIdentifier = supportForFile(left.file, languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65607
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(left.file, languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65306
65608
  return fileIdentityKey(left.file) === fileIdentityKey(right.file) && normalizeIdentifier(left.localName) === normalizeIdentifier(right.localName) && leftIndex === rightIndex;
65307
65609
  }
65308
65610
  function rangeContains(range, pos) {
@@ -65585,7 +65887,7 @@ function hasExpandedNamedImport(moduleIndex, targetFile, symbolName) {
65585
65887
  return moduleIndex.imports.some((candidate) => candidate.kind === "named" && candidate.local === symbolName && candidate.imported === symbolName && typeof candidate.resolved === "string" && fileIdentityKey(candidate.resolved) === targetKey);
65586
65888
  }
65587
65889
  function referenceCandidateCacheKey(index, def, exportedNames) {
65588
- const normalizeIdentifier = supportForFile(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65890
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(def.file, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
65589
65891
  const sortedNames = exportedNames.map(normalizeIdentifier).sort();
65590
65892
  return `${fileIdentityKey(def.file)}::${def.range.start.index ?? 0}::canonical::${sortedNames.join("\0")}`;
65591
65893
  }
@@ -66363,7 +66665,7 @@ async function findReferences(index, req, opts) {
66363
66665
  const filter = index.bloomFilters?.get(fileIdentityKey(candidateFile));
66364
66666
  if (!filter)
66365
66667
  return true;
66366
- const normalizeIdentifier = supportForFile(candidateFile, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
66668
+ const normalizeIdentifier = supportForFileWithoutHeaderSample(candidateFile, index.languageExtensions)?.normalizeIdentifier ?? ((name) => name);
66367
66669
  const aliases = getCandidateReferenceNames(module2, definitionFile, exportedNameSet);
66368
66670
  if (!aliases.length) {
66369
66671
  return [...exportedNames, ...phpQualifiedNames].some((candidateName) => filter.mightContain(normalizeIdentifier(candidateName)));
@@ -66393,7 +66695,7 @@ async function findReferences(index, req, opts) {
66393
66695
  }
66394
66696
  return scopeIndex;
66395
66697
  };
66396
- if (supportForFile(fileId, index.languageExtensions)?.supportsExportFromReferences) {
66698
+ if (supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.supportsExportFromReferences) {
66397
66699
  for (const entry of module2.exports) {
66398
66700
  if (hasReachedMaxReferences())
66399
66701
  break;
@@ -66521,7 +66823,7 @@ async function findReferences(index, req, opts) {
66521
66823
  if (hasReachedMaxReferences())
66522
66824
  break;
66523
66825
  const filter = index.bloomFilters?.get(fileIdentityKey(fileId));
66524
- const canonicalName = supportForFile(fileId, index.languageExtensions)?.normalizeIdentifier(def.localName) ?? def.localName;
66826
+ const canonicalName = supportForFileWithoutHeaderSample(fileId, index.languageExtensions)?.normalizeIdentifier(def.localName) ?? def.localName;
66525
66827
  if (filter && !filter.mightContain(canonicalName))
66526
66828
  continue;
66527
66829
  const remainingReferences = maxReferences !== void 0 ? Math.max(0, maxReferences - refs.length) : void 0;
@@ -68023,7 +68325,7 @@ function hasDiagnostics(diagnostics) {
68023
68325
  return !!(diagnostics.missingFiles.length || diagnostics.symbolMappingParseFailures.length || diagnostics.memberResolutionCoverage?.limitedLanguages.length);
68024
68326
  }
68025
68327
  function isRiskRelevantSymbolMappingFile(file2) {
68026
- return supportForFile(file2)?.supportsCrossModuleSymbols ?? false;
68328
+ return supportForFileWithoutHeaderSample(file2)?.supportsCrossModuleSymbols ?? false;
68027
68329
  }
68028
68330
  var init_risk = __esm({
68029
68331
  "dist/review/risk.js"() {
@@ -69919,7 +70221,7 @@ async function collectVerifiedCallsiteReferences(index, changedSymbol, maxRefs,
69919
70221
  if (!shouldIncludeReference(file2)) {
69920
70222
  continue;
69921
70223
  }
69922
- const support = supportForFile(file2);
70224
+ const support = supportForFileWithoutHeaderSample(file2, index.languageExtensions);
69923
70225
  if (!support || !supportsCallCompatibilityLanguage(support.id)) {
69924
70226
  continue;
69925
70227
  }
@@ -70332,7 +70634,7 @@ var init_hunks = __esm({
70332
70634
  // dist/impact/map.js
70333
70635
  async function locateChangedSymbolsWithLines(index, file2, hunks) {
70334
70636
  const changedLines = collectChangedLines(hunks);
70335
- if (isGraphOnlyFile(file2)) {
70637
+ if (isGraphOnlyFile(file2, index.languageExtensions)) {
70336
70638
  return { changedSymbols: [], changedLines, parseFailed: false };
70337
70639
  }
70338
70640
  let parsedEntry;
@@ -70472,7 +70774,7 @@ function sameRangeStartPosition(left, right) {
70472
70774
  return left.start.line === right.start.line && left.start.column === right.start.column && left.start.index === right.start.index;
70473
70775
  }
70474
70776
  async function mapChangedLinesToSymbols(index, file2, hunks, changedLinesOverride) {
70475
- if (isGraphOnlyFile(file2)) {
70777
+ if (isGraphOnlyFile(file2, index.languageExtensions)) {
70476
70778
  return /* @__PURE__ */ new Map();
70477
70779
  }
70478
70780
  let parsedEntry;
@@ -70513,8 +70815,8 @@ async function mapChangedLinesToSymbols(index, file2, hunks, changedLinesOverrid
70513
70815
  }
70514
70816
  return linesByHandle;
70515
70817
  }
70516
- function isGraphOnlyFile(file2) {
70517
- const support = supportForFile(file2);
70818
+ function isGraphOnlyFile(file2, languageExtensions) {
70819
+ const support = supportForFileWithoutHeaderSample(file2, languageExtensions);
70518
70820
  return support ? isGraphOnlyLanguage(support.id) : false;
70519
70821
  }
70520
70822
  function hasOverlapSorted(sorted, lo, hi) {
@@ -73054,17 +73356,25 @@ function isNodeBuiltinSpecifier(specifier) {
73054
73356
  return NODE_BUILTIN_MODULES2.has(specifier);
73055
73357
  }
73056
73358
  function isGraphOnlyImporter(file2) {
73057
- const support = supportForFile(file2);
73359
+ const support = supportForFileWithoutHeaderSample(file2);
73058
73360
  return support ? isGraphOnlyLanguage(support.id) : false;
73059
73361
  }
73060
73362
  function getUnresolvedImports(graph, opts = {}) {
73061
73363
  const unresolved = /* @__PURE__ */ new Map();
73062
73364
  const classificationCache = /* @__PURE__ */ new Map();
73365
+ const graphOnlyImporterCache = /* @__PURE__ */ new Map();
73063
73366
  for (const edge of graph.edges) {
73064
73367
  if (edge.to.type !== "external")
73065
73368
  continue;
73066
- if (!opts.includeGraphOnly && isGraphOnlyImporter(edge.from))
73067
- continue;
73369
+ if (!opts.includeGraphOnly) {
73370
+ let graphOnly = graphOnlyImporterCache.get(edge.from);
73371
+ if (graphOnly === void 0) {
73372
+ graphOnly = isGraphOnlyImporter(edge.from);
73373
+ graphOnlyImporterCache.set(edge.from, graphOnly);
73374
+ }
73375
+ if (graphOnly)
73376
+ continue;
73377
+ }
73068
73378
  if (isNodeBuiltinSpecifier(edge.to.name) || isNodeBuiltinSpecifier(edge.raw))
73069
73379
  continue;
73070
73380
  const classificationKey = `${edge.from}\0${edge.to.name}\0${edge.raw}\0${opts.projectRoot ?? ""}`;
@@ -74135,7 +74445,9 @@ function detectQueryIndexSurface(relativePath3) {
74135
74445
  return "code";
74136
74446
  }
74137
74447
  function buildQueryTextChunks(file2, text) {
74138
- const support = supportForFile(file2);
74448
+ return chunkQueryText(file2, text, supportForFileWithSource(file2, text));
74449
+ }
74450
+ function chunkQueryText(file2, text, support) {
74139
74451
  const languageId = support ? CHUNK_LANGUAGE_ALIASES[support.id] ?? support.id : void 0;
74140
74452
  const language = languageId ? LANG_CONFIGS[languageId] : void 0;
74141
74453
  if (language) {
@@ -74173,13 +74485,13 @@ function buildQueryTextChunks(file2, text) {
74173
74485
  async function prepareQueryIndexFile(input) {
74174
74486
  try {
74175
74487
  const stat = await fs32.stat(input.absolutePath);
74176
- const support = supportForFile(input.absolutePath);
74177
74488
  if (stat.size > MAX_QUERY_INDEX_TEXT_BYTES) {
74489
+ const support2 = supportForFile(input.absolutePath);
74178
74490
  return {
74179
74491
  path: input.path,
74180
74492
  sourceIdentity: input.sourceIdentity,
74181
74493
  surface: detectQueryIndexSurface(input.path),
74182
- ...support ? { language: support.id } : {},
74494
+ ...support2 ? { language: support2.id } : {},
74183
74495
  byteLength: stat.size,
74184
74496
  lineCount: 0,
74185
74497
  normalizedText: compressQueryText(""),
@@ -74188,6 +74500,7 @@ async function prepareQueryIndexFile(input) {
74188
74500
  };
74189
74501
  }
74190
74502
  const text = await fs32.readFile(input.absolutePath, "utf8");
74503
+ const support = supportForFileWithSource(input.absolutePath, text);
74191
74504
  return {
74192
74505
  path: input.path,
74193
74506
  sourceIdentity: input.sourceIdentity,
@@ -74196,7 +74509,7 @@ async function prepareQueryIndexFile(input) {
74196
74509
  byteLength: stat.size,
74197
74510
  lineCount: text ? text.split(/\r?\n/).length : 0,
74198
74511
  normalizedText: compressQueryText(normalizeQuerySearchText(text)),
74199
- chunks: buildQueryTextChunks(input.absolutePath, text).map((chunk) => ({
74512
+ chunks: chunkQueryText(input.absolutePath, text, support).map((chunk) => ({
74200
74513
  ...chunk,
74201
74514
  text: compressQueryText(chunk.text)
74202
74515
  })),
@@ -82485,15 +82798,16 @@ function validateNewName(snapshot, def, newName) {
82485
82798
  const file2 = normalizeAgentFilePath(snapshot.root, def.file);
82486
82799
  const conflicts = [];
82487
82800
  const invalidPathCharacters = newName.includes("/") || newName.includes("\\") || newName.includes("\0");
82488
- const support = supportForFile(def.file, snapshot.index.languageExtensions);
82801
+ const support = supportForFileWithoutHeaderSample(def.file, snapshot.index.languageExtensions);
82489
82802
  const allowsDollar = support?.id === "js" || support?.id === "ts" || support?.id === "tsx";
82490
82803
  const identifierPattern = allowsDollar ? /^[$_\p{ID_Start}](?:[$_\p{ID_Continue}]|\u200c|\u200d)*$/u : /^[_\p{ID_Start}][_\p{ID_Continue}]*$/u;
82491
82804
  if (!newName || invalidPathCharacters || !identifierPattern.test(newName)) {
82805
+ const displaySupport = supportForFile(def.file, snapshot.index.languageExtensions);
82492
82806
  conflicts.push({
82493
82807
  file: file2,
82494
82808
  location: { file: file2, range: def.range },
82495
82809
  reason: "invalid_identifier",
82496
- message: `"${newName}" is not a valid ${support?.id ?? "conservative"} identifier.`
82810
+ message: `"${newName}" is not a valid ${displaySupport?.id ?? "conservative"} identifier.`
82497
82811
  });
82498
82812
  }
82499
82813
  if (newName !== def.localName && newName.toLocaleLowerCase() === def.localName.toLocaleLowerCase()) {