react-doctor 0.8.1-dev.61bf03e → 0.8.1-dev.7818922

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.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c5ad9312-01de-535b-a900-0d45e296a4fa")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9e32582f-b296-5216-a028-7cc19ed83931")}catch(e){}}();
3
3
  import { createRequire } from "node:module";
4
4
  import * as NodeChildProcess from "node:child_process";
5
5
  import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
@@ -37317,10 +37317,6 @@ const listWorkspacePackages = (rootDirectory) => {
37317
37317
  return packages;
37318
37318
  };
37319
37319
  const REANIMATED_DEPENDENCY_NAME = "react-native-reanimated";
37320
- const MOBX_REACT_PACKAGE_NAME = "mobx-react";
37321
- const MOBX_REACT_LITE_PACKAGE_NAME = "mobx-react-lite";
37322
- const MOBX_STATE_TREE_PACKAGE_NAME = "mobx-state-tree";
37323
- const MOBX_REACT_OBSERVER_PACKAGE_NAME = "mobx-react-observer";
37324
37320
  const SHOPIFY_FLASH_LIST_PACKAGE_NAME = "@shopify/flash-list";
37325
37321
  const resolveWorkspaceDependencyVersion = ({ concreteVersion, packageName, rootDirectory, rootPackageJson, sections, workspaceDirectory, workspacePackageJson }) => {
37326
37322
  const dependencyDeclaration = getDependencyDeclaration({
@@ -37339,18 +37335,7 @@ const shouldReplaceReactVersion = (currentVersion, nextVersion) => {
37339
37335
  if (nextMajor === null) return false;
37340
37336
  return nextMajor < currentMajor;
37341
37337
  };
37342
- const shouldReplaceMobxFact = (currentFact, nextFact) => {
37343
- if (currentFact.version === null) return true;
37344
- if (nextFact.version === null) return false;
37345
- const currentMajor = getLowestDependencyMajor(currentFact.version);
37346
- const nextMajor = getLowestDependencyMajor(nextFact.version);
37347
- if (currentMajor === null) return false;
37348
- if (nextMajor === null) return true;
37349
- if (currentMajor > 6) return false;
37350
- if (nextMajor > 6) return true;
37351
- return nextMajor < currentMajor;
37352
- };
37353
- const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, rootPackageJson) => {
37338
+ const evaluateManifestFacts = (facts, packageJson, directory) => {
37354
37339
  if (facts.expo.version === null) {
37355
37340
  const spec = getDependencySpec(packageJson, "expo");
37356
37341
  if (spec !== null) facts.expo = {
@@ -37372,52 +37357,13 @@ const evaluateManifestFacts = (facts, packageJson, directory, rootDirectory, roo
37372
37357
  sourceDirectory: directory
37373
37358
  };
37374
37359
  }
37375
- const mobxSpec = getDependencySpec(packageJson, "mobx");
37376
- if (mobxSpec !== null) {
37377
- const nextMobxFact = {
37378
- version: resolveCatalogBackedDependencyVersion({
37379
- rootDirectory: directory,
37380
- rootPackageJson: packageJson,
37381
- packageName: "mobx",
37382
- version: mobxSpec
37383
- }),
37384
- sourceDirectory: directory
37385
- };
37386
- if (shouldReplaceMobxFact(facts.mobx, nextMobxFact)) facts.mobx = nextMobxFact;
37387
- }
37388
- facts.hasMobxReact = facts.hasMobxReact || getDependencySpec(packageJson, MOBX_REACT_PACKAGE_NAME) !== null;
37389
- facts.hasMobxReactLite = facts.hasMobxReactLite || getDependencySpec(packageJson, MOBX_REACT_LITE_PACKAGE_NAME) !== null;
37390
- facts.hasMobxStateTree = facts.hasMobxStateTree || getDependencySpec(packageJson, MOBX_STATE_TREE_PACKAGE_NAME) !== null;
37391
- facts.hasMobxReactObserver = facts.hasMobxReactObserver || getDependencySpec(packageJson, MOBX_REACT_OBSERVER_PACKAGE_NAME) !== null;
37392
37360
  if (facts.reanimatedVersion === null) {
37393
37361
  const spec = getDependencySpec(packageJson, REANIMATED_DEPENDENCY_NAME);
37394
37362
  if (spec !== null) facts.reanimatedVersion = spec;
37395
37363
  }
37396
- if (facts.valtioVersion === null) {
37397
- const spec = getDependencySpec(packageJson, "valtio");
37398
- if (spec !== null) facts.valtioVersion = spec;
37399
- }
37400
37364
  facts.hasReactNativeAwarePackage = facts.hasReactNativeAwarePackage || isPackageJsonReactNativeAware(packageJson);
37401
37365
  facts.hasReanimatedAwarePackage = facts.hasReanimatedAwarePackage || isPackageJsonReanimatedAware(packageJson);
37402
37366
  facts.hasSsrDependency = facts.hasSsrDependency || isPackageJsonSsrAware(packageJson);
37403
- const remotionSpec = getDependencySpec(packageJson, "remotion");
37404
- if (remotionSpec !== null) {
37405
- facts.hasRemotionDependency = true;
37406
- const resolvedRemotionVersion = resolveCatalogBackedDependencyVersion({
37407
- rootDirectory,
37408
- rootPackageJson,
37409
- packageName: "remotion",
37410
- version: remotionSpec
37411
- });
37412
- const remotionMajorVersion = resolvedRemotionVersion === null ? null : getLowestDependencyMajor(resolvedRemotionVersion);
37413
- if (remotionMajorVersion === null) {
37414
- facts.hasUnknownRemotionVersion = true;
37415
- facts.remotionVersion = null;
37416
- } else if (!facts.hasUnknownRemotionVersion) {
37417
- const currentRemotionMajorVersion = facts.remotionVersion === null ? null : getLowestDependencyMajor(facts.remotionVersion);
37418
- if (currentRemotionMajorVersion === null || remotionMajorVersion < currentRemotionMajorVersion) facts.remotionVersion = resolvedRemotionVersion;
37419
- }
37420
- }
37421
37367
  };
37422
37368
  const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGroup }) => {
37423
37369
  const facts = {
@@ -37437,24 +37383,12 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
37437
37383
  version: null,
37438
37384
  sourceDirectory: null
37439
37385
  },
37440
- valtioVersion: null,
37441
- mobx: {
37442
- version: null,
37443
- sourceDirectory: null
37444
- },
37445
- hasMobxReact: false,
37446
- hasMobxReactLite: false,
37447
- hasMobxStateTree: false,
37448
- hasMobxReactObserver: false,
37449
37386
  hasReactNativeAwarePackage: false,
37450
37387
  hasReanimatedAwarePackage: false,
37451
37388
  hasSsrDependency: false,
37452
- hasRemotionDependency: false,
37453
- hasUnknownRemotionVersion: false,
37454
- remotionVersion: null,
37455
37389
  reanimatedVersion: null
37456
37390
  };
37457
- evaluateManifestFacts(facts, rootPackageJson, rootDirectory, rootDirectory, rootPackageJson);
37391
+ evaluateManifestFacts(facts, rootPackageJson, rootDirectory);
37458
37392
  let isReactGroupSettled = !collectReactGroup;
37459
37393
  const visitedDirectories = /* @__PURE__ */ new Set();
37460
37394
  for (const pattern of getWorkspacePatterns(rootDirectory, rootPackageJson)) {
@@ -37463,7 +37397,7 @@ const collectWorkspaceFacts = (rootDirectory, rootPackageJson, { collectReactGro
37463
37397
  if (visitedDirectories.has(workspaceDirectory)) continue;
37464
37398
  visitedDirectories.add(workspaceDirectory);
37465
37399
  const workspacePackageJson = readPackageJson$1(Path.join(workspaceDirectory, "package.json"));
37466
- evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory, rootDirectory, rootPackageJson);
37400
+ evaluateManifestFacts(facts, workspacePackageJson, workspaceDirectory);
37467
37401
  const info = extractDependencyInfo(workspacePackageJson);
37468
37402
  if (info.framework !== "unknown" && frameworkMergeRank(info.framework) < frameworkMergeRank(facts.framework)) facts.framework = info.framework;
37469
37403
  if (isReactGroupSettled) continue;
@@ -37684,22 +37618,11 @@ const discoverProjectWithoutPackageJson = (directory) => {
37684
37618
  tailwindVersion: null,
37685
37619
  zodVersion: null,
37686
37620
  zodMajorVersion: null,
37687
- mobxVersion: null,
37688
- mobxMajorVersion: null,
37689
- hasMobxReact: false,
37690
- hasMobxReactLite: false,
37691
- hasMobxStateTree: false,
37692
- hasMobxReactObserver: false,
37693
37621
  framework: "unknown",
37694
37622
  hasTypeScript: hasOwnTsConfig,
37695
37623
  hasReactCompiler: false,
37696
37624
  hasReactCompilerLintPlugin: false,
37697
37625
  hasTanStackQuery: false,
37698
- valtioVersion: null,
37699
- valtioMajorVersion: null,
37700
- hasRemotion: false,
37701
- remotionVersion: null,
37702
- remotionMajorVersion: null,
37703
37626
  hasSsrDependency: false,
37704
37627
  preactVersion: null,
37705
37628
  preactMajorVersion: null,
@@ -37806,20 +37729,7 @@ const discoverProject = (directory) => {
37806
37729
  packageName: "next",
37807
37730
  version: workspaceFacts.next.version
37808
37731
  }) : null;
37809
- const valtioVersion = resolveCatalogBackedDependencyVersion({
37810
- rootDirectory: directory,
37811
- rootPackageJson: packageJson,
37812
- packageName: "valtio",
37813
- version: workspaceFacts.valtioVersion
37814
- });
37815
- const mobxVersion = resolveCatalogBackedDependencyVersion({
37816
- rootDirectory: directory,
37817
- rootPackageJson: packageJson,
37818
- packageName: "mobx",
37819
- version: workspaceFacts.mobx.version
37820
- });
37821
37732
  const preactVersion = getPreactVersion(packageJson);
37822
- const remotionVersion = workspaceFacts.remotionVersion;
37823
37733
  const isPreES2023Target = hasTypeScript && detectPreES2023Target(directory);
37824
37734
  const projectInfo = {
37825
37735
  rootDirectory: directory,
@@ -37829,22 +37739,11 @@ const discoverProject = (directory) => {
37829
37739
  tailwindVersion,
37830
37740
  zodVersion,
37831
37741
  zodMajorVersion: zodVersion === null ? null : getLowestDependencyMajor(zodVersion),
37832
- mobxVersion,
37833
- mobxMajorVersion: mobxVersion === null ? null : getLowestDependencyMajor(mobxVersion),
37834
- hasMobxReact: workspaceFacts.hasMobxReact,
37835
- hasMobxReactLite: workspaceFacts.hasMobxReactLite,
37836
- hasMobxStateTree: workspaceFacts.hasMobxStateTree,
37837
- hasMobxReactObserver: workspaceFacts.hasMobxReactObserver,
37838
37742
  framework,
37839
37743
  hasTypeScript,
37840
37744
  hasReactCompiler: detectReactCompiler(directory, packageJson),
37841
37745
  hasReactCompilerLintPlugin: detectReactCompilerLintPlugin(directory, packageJson),
37842
37746
  hasTanStackQuery: hasTanStackQuery(packageJson),
37843
- valtioVersion,
37844
- valtioMajorVersion: valtioVersion === null ? null : getLowestDependencyMajor(valtioVersion),
37845
- hasRemotion: workspaceFacts.hasRemotionDependency,
37846
- remotionVersion,
37847
- remotionMajorVersion: remotionVersion === null ? null : getLowestDependencyMajor(remotionVersion),
37848
37747
  hasSsrDependency: workspaceFacts.hasSsrDependency,
37849
37748
  preactVersion,
37850
37749
  preactMajorVersion: parseReactMajor(preactVersion),
@@ -38078,6 +37977,7 @@ const LEGACY_RULE_KEY_TO_NATIVE_RULE_KEY = {
38078
37977
  "react/jsx-no-new-function-as-prop": "react-doctor/jsx-no-new-function-as-prop",
38079
37978
  "react/jsx-no-new-object-as-prop": "react-doctor/jsx-no-new-object-as-prop",
38080
37979
  "react/jsx-no-script-url": "react-doctor/jsx-no-script-url",
37980
+ "react/jsx-no-target-blank": "react-doctor/jsx-no-target-blank",
38081
37981
  "react/jsx-no-undef": "react-doctor/jsx-no-undef",
38082
37982
  "react/jsx-no-useless-fragment": "react-doctor/jsx-no-useless-fragment",
38083
37983
  "react/jsx-pascal-case": "react-doctor/jsx-pascal-case",
@@ -40399,25 +40299,9 @@ const BABEL_CONFIG_FILE_NAMES = [
40399
40299
  ".babelrc.json"
40400
40300
  ];
40401
40301
  const LEGACY_PRESET_SPEC = "module:metro-react-native-babel-preset";
40402
- const LEGACY_PRESET_PACKAGE = "metro-react-native-babel-preset";
40403
- const REACT_NATIVE_PACKAGE = "react-native";
40404
- const PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION = "0.73.0";
40405
- const LEGACY_PRESET_REFERENCE = new RegExp(`['"]${LEGACY_PRESET_SPEC}['"]`);
40406
40302
  const MODERN_PRESET_REFERENCE = new RegExp(`['"]module:@react-native/babel-preset['"]`);
40407
40303
  const ENABLE_BABEL_RUNTIME_VERSION = /enableBabelRuntime["']?\s*:\s*['"]/;
40408
- const isReactNativeVersionAtLeastPresetRename = (rootDirectory, packageJson) => {
40409
- const installedReactNativeManifestPath = Path.join(rootDirectory, "node_modules", REACT_NATIVE_PACKAGE, "package.json");
40410
- const reactNativeVersionSpec = (isFile(installedReactNativeManifestPath) ? readPackageJson$1(installedReactNativeManifestPath).version : void 0) ?? getDependencySpec(packageJson, REACT_NATIVE_PACKAGE);
40411
- if (reactNativeVersionSpec === null || reactNativeVersionSpec === void 0) return false;
40412
- const normalizedVersionRange = import_semver.validRange(reactNativeVersionSpec);
40413
- if (normalizedVersionRange === null) return false;
40414
- const minimumVersion = import_semver.minVersion(normalizedVersionRange);
40415
- return minimumVersion !== null && import_semver.gte(minimumVersion, PRESET_RENAME_MINIMUM_REACT_NATIVE_VERSION);
40416
- };
40417
- const canResolveLegacyPreset = (rootDirectory, packageJson) => getDependencySpec(packageJson, LEGACY_PRESET_PACKAGE) !== null || isFile(Path.join(rootDirectory, "node_modules", LEGACY_PRESET_PACKAGE, "package.json"));
40418
40304
  const checkReactNativeMetroBabelPreset = (rootDirectory) => {
40419
- const packageJson = readPackageJson$1(Path.join(rootDirectory, "package.json"));
40420
- const shouldReportLegacyPreset = isReactNativeVersionAtLeastPresetRename(rootDirectory, packageJson) && !canResolveLegacyPreset(rootDirectory, packageJson);
40421
40305
  for (const fileName of BABEL_CONFIG_FILE_NAMES) {
40422
40306
  const filePath = Path.join(rootDirectory, fileName);
40423
40307
  if (!isFile(filePath)) continue;
@@ -40427,7 +40311,7 @@ const checkReactNativeMetroBabelPreset = (rootDirectory) => {
40427
40311
  } catch {
40428
40312
  continue;
40429
40313
  }
40430
- if (shouldReportLegacyPreset && LEGACY_PRESET_REFERENCE.test(contents)) return [buildReactNativeDiagnostic({
40314
+ if (contents.includes(LEGACY_PRESET_SPEC)) return [buildReactNativeDiagnostic({
40431
40315
  filePath: fileName,
40432
40316
  rule: "rn-no-metro-babel-preset",
40433
40317
  severity: "error",
@@ -40450,6 +40334,12 @@ const checkReactNativeProject = (rootDirectory, project) => {
40450
40334
  return [...checkReactNativeMetroBabelPreset(rootDirectory), ...checkReactNativeLibraryDependencies(rootDirectory)];
40451
40335
  };
40452
40336
  const RULE_KEY = "no-vulnerable-react-server-components";
40337
+ const DEPENDENCY_SECTIONS = [
40338
+ "dependencies",
40339
+ "devDependencies",
40340
+ "peerDependencies",
40341
+ "optionalDependencies"
40342
+ ];
40453
40343
  const REACT_RSC_ADVISORIES_BY_MINOR = {
40454
40344
  "19.0": {
40455
40345
  rceFixedVersion: "19.0.1",
@@ -40496,13 +40386,20 @@ const enumerateWorkspaceDirectories = (workspaceRoot) => {
40496
40386
  for (const pattern of patterns) for (const directory of resolveWorkspaceDirectories(workspaceRoot, pattern)) directories.add(directory);
40497
40387
  return [...directories];
40498
40388
  };
40389
+ const readDeclaredSpec = (packageJson, packageName) => {
40390
+ for (const section of DEPENDENCY_SECTIONS) {
40391
+ const spec = packageJson[section]?.[packageName];
40392
+ if (typeof spec === "string") return spec;
40393
+ }
40394
+ return null;
40395
+ };
40499
40396
  const resolveVersionInDirectory = (directory, packageName, declaredSpecOverride) => {
40500
40397
  const manifestPath = Path.join(directory, "node_modules", packageName, "package.json");
40501
40398
  if (isFile(manifestPath)) {
40502
40399
  const installedVersion = import_semver.valid(readPackageJson$1(manifestPath).version ?? null);
40503
40400
  if (installedVersion !== null) return installedVersion;
40504
40401
  }
40505
- const candidateSpecs = [getDependencySpec(readPackageJson$1(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
40402
+ const candidateSpecs = [readDeclaredSpec(readPackageJson$1(Path.join(directory, "package.json")), packageName), declaredSpecOverride];
40506
40403
  for (const spec of candidateSpecs) {
40507
40404
  const pinnedVersion = spec === null ? null : import_semver.valid(spec);
40508
40405
  if (pinnedVersion !== null) return pinnedVersion;
@@ -41182,22 +41079,9 @@ const buildCapabilities = (project) => {
41182
41079
  })) capabilities.add("tailwind:3.4");
41183
41080
  if (project.zodVersion !== null) capabilities.add("zod");
41184
41081
  if (project.zodMajorVersion !== null && project.zodMajorVersion >= 4) capabilities.add("zod:4");
41185
- if (project.mobxVersion !== void 0 && project.mobxVersion !== null || project.hasMobxReact === true || project.hasMobxReactLite === true || project.hasMobxStateTree === true || project.hasMobxReactObserver === true) capabilities.add("mobx");
41186
- if (project.hasMobxReact === true) capabilities.add("mobx-react");
41187
- if (project.hasMobxReactLite === true) capabilities.add("mobx-react-lite");
41188
- if (project.hasMobxReact === true || project.hasMobxReactLite === true) capabilities.add("mobx-react-binding");
41189
- if (project.hasMobxStateTree === true) capabilities.add("mobx-state-tree");
41190
- if (project.hasMobxReactObserver === true) capabilities.add("mobx-react-observer");
41191
- if (project.mobxMajorVersion !== void 0 && project.mobxMajorVersion !== null && project.mobxMajorVersion >= 4 && project.mobxMajorVersion <= 6) addMajorLadder(capabilities, "mobx", project.mobxMajorVersion, 4, 6);
41192
41082
  if (project.isPreES2023Target) capabilities.add("pre-es2023");
41193
41083
  if (project.hasReactCompiler) capabilities.add("react-compiler");
41194
41084
  if (project.hasTanStackQuery) capabilities.add("tanstack-query");
41195
- if (project.valtioVersion !== null) capabilities.add("valtio");
41196
- addMajorLadder(capabilities, "valtio", project.valtioMajorVersion, 1, 10);
41197
- if (project.hasRemotion) {
41198
- capabilities.add("remotion");
41199
- addMajorLadder(capabilities, "remotion", project.remotionMajorVersion ?? null, 4, 30);
41200
- }
41201
41085
  if (project.hasTypeScript) capabilities.add("typescript");
41202
41086
  if (project.preactVersion !== null) capabilities.add("preact");
41203
41087
  addMajorLadder(capabilities, "preact", project.preactMajorVersion, 10, 20);
@@ -42450,35 +42334,6 @@ const parseGithubViewerPermission = (stdout) => {
42450
42334
  return /^[A-Z_]+$/.test(value) ? value.toLowerCase() : null;
42451
42335
  };
42452
42336
  const splitNullSeparated = (value) => value.split("\0").filter((entry) => entry.length > 0);
42453
- const parseBaselineDiffPlan = (value) => {
42454
- const entries = splitNullSeparated(value);
42455
- const baseFiles = /* @__PURE__ */ new Set();
42456
- const headFiles = /* @__PURE__ */ new Set();
42457
- for (let entryIndex = 0; entryIndex < entries.length; entryIndex += 2) {
42458
- const status = entries[entryIndex];
42459
- const filePath = entries[entryIndex + 1];
42460
- if (status === void 0 || filePath === void 0 || status.length !== 1) return null;
42461
- if (status === "A") {
42462
- headFiles.add(filePath);
42463
- continue;
42464
- }
42465
- if (status === "D") {
42466
- baseFiles.add(filePath);
42467
- continue;
42468
- }
42469
- if (status === "M" || status === "T") {
42470
- baseFiles.add(filePath);
42471
- headFiles.add(filePath);
42472
- continue;
42473
- }
42474
- return null;
42475
- }
42476
- return {
42477
- baseFiles: [...baseFiles],
42478
- headFiles: [...headFiles],
42479
- untrackedFiles: []
42480
- };
42481
- };
42482
42337
  const UNTRACKED_FILE_LAST_LINE = Number.MAX_SAFE_INTEGER;
42483
42338
  /**
42484
42339
  * `Git` wraps every `git`-via-subprocess call react-doctor makes
@@ -42681,45 +42536,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
42681
42536
  githubViewerPermission,
42682
42537
  branchExists,
42683
42538
  mergeBase,
42684
- baselineDiffPlan: (input) => {
42685
- if (!isSafeGitRevision(input.ref)) return succeed$2(null);
42686
- return gen(function* () {
42687
- const unmerged = yield* runGit(input.directory, [
42688
- "diff",
42689
- "--no-ext-diff",
42690
- "-z",
42691
- "--name-only",
42692
- "--diff-filter=U",
42693
- "--relative"
42694
- ]);
42695
- if (unmerged.status !== 0 || unmerged.stdout.length > 0) return null;
42696
- const result = yield* runGit(input.directory, [
42697
- "diff",
42698
- "--no-ext-diff",
42699
- "--no-textconv",
42700
- "--no-renames",
42701
- "-z",
42702
- "--name-status",
42703
- "--relative",
42704
- input.ref
42705
- ]);
42706
- if (result.status !== 0) return null;
42707
- const plan = parseBaselineDiffPlan(result.stdout);
42708
- if (plan === null) return null;
42709
- const untracked = yield* runGit(input.directory, [
42710
- "ls-files",
42711
- "--others",
42712
- "--exclude-standard",
42713
- "-z"
42714
- ]);
42715
- if (untracked.status !== 0) return null;
42716
- return {
42717
- baseFiles: plan.baseFiles,
42718
- headFiles: plan.headFiles,
42719
- untrackedFiles: splitNullSeparated(untracked.stdout)
42720
- };
42721
- }).pipe(catch_$1(() => succeed$2(null)), withSpan("Git.baselineDiffPlan"));
42722
- },
42723
42539
  diffSelection: ({ directory, explicitBaseBranch, includeUntracked = false }) => gen(function* () {
42724
42540
  if (explicitBaseBranch !== void 0 && explicitBaseBranch.trim().length === 0) return yield* fail$4(new ReactDoctorError({ reason: new GitBaseBranchInvalid({ detail: "Diff base branch cannot be empty." }) }));
42725
42541
  if (explicitBaseBranch !== void 0) {
@@ -42869,7 +42685,6 @@ var Git = class Git extends Service()("react-doctor/Git") {
42869
42685
  githubViewerPermission: () => succeed$2(snapshot.githubViewerPermission ?? null),
42870
42686
  branchExists: (_directory, branch) => succeed$2(snapshot.branchExists?.get(branch) ?? false),
42871
42687
  mergeBase: ({ ref }) => succeed$2(snapshot.mergeBase?.get(ref) ?? null),
42872
- baselineDiffPlan: () => succeed$2(snapshot.baselineDiffPlan ?? null),
42873
42688
  diffSelection: () => succeed$2(snapshot.diffSelection ?? null),
42874
42689
  stagedFilePaths: () => succeed$2(snapshot.stagedFiles ?? []),
42875
42690
  showStagedContent: (_directory, relativePath) => succeed$2(snapshot.stagedContent?.get(relativePath) ?? null),
@@ -44207,17 +44022,12 @@ const REACT_ERROR_BOUNDARY_MESSAGE = "This try/catch cannot catch errors thrown
44207
44022
  const REACT_COMPILER_IMPACT = "This component misses React Compiler's automatic memoization & re-renders more than it should";
44208
44023
  const REACT_COMPILER_ACTION = "Rewrite the flagged code so the compiler can optimize it.";
44209
44024
  const REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION = "It's how the library works, not a bug in your code. Memoize values you pass from it into other memoized components, or suppress it with `// react-doctor-disable-next-line react-hooks-js/incompatible-library`.";
44210
- const SET_STATE_IN_EFFECT_ACTION = "Prefer deriving or initializing the value before render. If the effect must read a browser API after mount, treat this as advisory or suppress it with `// react-doctor-disable-next-line react-hooks-js/set-state-in-effect`.";
44211
44025
  const REACT_COMPILER_GENERIC_MESSAGE = `${REACT_COMPILER_IMPACT}. ${REACT_COMPILER_ACTION}`;
44212
44026
  const buildReactCompilerMessage = (reasonSummary, action = REACT_COMPILER_ACTION) => {
44213
44027
  const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
44214
44028
  if (!normalizedSummary) return `${REACT_COMPILER_IMPACT}. ${action}`;
44215
44029
  return `${REACT_COMPILER_IMPACT}: ${normalizedSummary}. ${action}`;
44216
44030
  };
44217
- const buildSetStateInEffectMessage = (reasonSummary) => {
44218
- const normalizedSummary = reasonSummary.replace(TRAILING_PERIOD_PATTERN, "");
44219
- return `This synchronous effect update causes an extra render${normalizedSummary ? `: ${normalizedSummary}` : ""}. ${SET_STATE_IN_EFFECT_ACTION}`;
44220
- };
44221
44031
  const PLUGIN_CATEGORY_MAP = {
44222
44032
  react: "Bugs",
44223
44033
  "react-hooks": "Bugs",
@@ -44275,10 +44085,6 @@ const resolveCleanedDiagnostic = (message, help, plugin, rule, project) => {
44275
44085
  message: REACT_ERROR_BOUNDARY_MESSAGE,
44276
44086
  help: reasonDetail || help
44277
44087
  };
44278
- if (rule === "set-state-in-effect") return {
44279
- message: buildSetStateInEffectMessage(reasonSummary.trim()),
44280
- help: reasonDetail || help
44281
- };
44282
44088
  return {
44283
44089
  message: buildReactCompilerMessage(reasonSummary.trim(), rule === "incompatible-library" ? REACT_COMPILER_INCOMPATIBLE_LIBRARY_ACTION : REACT_COMPILER_ACTION),
44284
44090
  help: appendReanimatedSharedValueHint(reasonDetail || help, rule, project)
@@ -46615,19 +46421,12 @@ const isPathInsideDirectory = (childAbsolutePath, parentAbsolutePath) => {
46615
46421
  */
46616
46422
  const materializeSourceTree = (input) => gen(function* () {
46617
46423
  const materializedFiles = [];
46618
- const unmaterializedFiles = [];
46619
46424
  const resolvedTempDirectory = path.resolve(input.tempDirectory);
46620
46425
  for (const relativePath of input.files) {
46621
46426
  const content = yield* input.readContent(relativePath).pipe(orElseSucceed(() => null));
46622
- if (content === null) {
46623
- unmaterializedFiles.push(relativePath);
46624
- continue;
46625
- }
46427
+ if (content === null) continue;
46626
46428
  const candidateTargetPath = path.resolve(resolvedTempDirectory, relativePath);
46627
- if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory)) {
46628
- unmaterializedFiles.push(relativePath);
46629
- continue;
46630
- }
46429
+ if (!isPathInsideDirectory(candidateTargetPath, resolvedTempDirectory)) continue;
46631
46430
  yield* sync(() => {
46632
46431
  fs.mkdirSync(path.dirname(candidateTargetPath), { recursive: true });
46633
46432
  fs.writeFileSync(candidateTargetPath, content);
@@ -46644,7 +46443,6 @@ const materializeSourceTree = (input) => gen(function* () {
46644
46443
  return {
46645
46444
  tempDirectory: input.tempDirectory,
46646
46445
  materializedFiles,
46647
- unmaterializedFiles,
46648
46446
  cleanup: () => {
46649
46447
  try {
46650
46448
  fs.rmSync(input.tempDirectory, {
@@ -46914,80 +46712,54 @@ const buildSkippedChecks = (input) => {
46914
46712
  skippedCheckReasons
46915
46713
  };
46916
46714
  };
46917
- const fingerprintText = (text) => createHash("sha256").update(text).digest("hex");
46918
- const normalizeEvidence = (evidence) => evidence.replace(/\s+/g, " ").trim();
46919
- const getDiagnosticMatchKeys = (diagnostic, evidence) => {
46715
+ const fingerprintDiagnostic = (diagnostic, lineText) => {
46920
46716
  const ruleKey = `${diagnostic.plugin}/${diagnostic.rule}`;
46921
- const messageFingerprint = fingerprintText(`${diagnostic.title ?? ""}\0${diagnostic.message}`);
46922
- const normalizedEvidence = evidence === null ? "" : normalizeEvidence(evidence);
46923
- const stableEvidenceKey = normalizedEvidence.length > 0 ? `evidence\0${ruleKey}\0${messageFingerprint}\0${fingerprintText(normalizedEvidence)}` : null;
46924
- return {
46925
- stableEvidenceKey,
46926
- sameFileStableEvidenceKey: stableEvidenceKey === null ? null : `${diagnostic.filePath}\0${stableEvidenceKey}`,
46927
- sameFileFallbackKey: diagnostic.matchByOccurrence || normalizedEvidence.length === 0 ? `fallback\0${diagnostic.filePath}\0${ruleKey}\0${messageFingerprint}` : null
46928
- };
46929
- };
46930
- const addDiagnosticIndex = (buckets, key, diagnosticIndex) => {
46931
- if (key === null) return;
46932
- const diagnosticIndexes = buckets.get(key) ?? [];
46933
- diagnosticIndexes.push(diagnosticIndex);
46934
- buckets.set(key, diagnosticIndexes);
46935
- };
46936
- const takeMatchingDiagnosticIndex = (buckets, key, matchedDiagnosticIndexes) => {
46937
- if (key === null) return null;
46938
- for (const diagnosticIndex of buckets.get(key) ?? []) if (!matchedDiagnosticIndexes.has(diagnosticIndex)) return diagnosticIndex;
46939
- return null;
46940
- };
46941
- const readDiagnosticEvidence = (diagnostic, readEvidence, readLine) => readEvidence?.(diagnostic) ?? readLine(diagnostic.filePath, diagnostic.line);
46942
- const buildMatchCandidates = (diagnostics, readEvidence, readLine) => diagnostics.map((diagnostic, diagnosticIndex) => ({
46943
- diagnosticIndex,
46944
- ...getDiagnosticMatchKeys(diagnostic, readDiagnosticEvidence(diagnostic, readEvidence, readLine))
46945
- }));
46946
- /**
46947
- * Diffs a head scan against a base scan using a multiset of construct-level
46948
- * evidence. Stable identities combine plugin/rule, the diagnostic message,
46949
- * and normalized diagnosed source, so unchanged findings can move across
46950
- * files while changed constructs or messages remain new. Cardinality is
46951
- * retained for identical findings. Diagnostics explicitly marked
46952
- * `matchByOccurrence` may fall back to same-file plugin/rule/message matching
46953
- * after same-file strict evidence matching. Cross-file evidence matching runs
46954
- * last so a copy cannot consume a reformatted local occurrence. Unreadable
46955
- * evidence uses the same conservative fallback rather than matching across
46956
- * files without proof.
46717
+ const snippet = lineText === null || diagnostic.matchByOccurrence ? "" : createHash("sha1").update(lineText.trim()).digest("hex");
46718
+ return `${diagnostic.filePath}\u0000${ruleKey}\u0000${snippet}`;
46719
+ };
46720
+ /**
46721
+ * Diffs a head scan against a base scan to isolate the diagnostics a change
46722
+ * introduced (and count the ones it resolved). Matching is a multiset over a
46723
+ * position-independent fingerprint — `(filePath, plugin/rule, hash(flagged
46724
+ * line text))` — so inserting lines above an existing issue doesn't make it
46725
+ * look new, while a genuinely new occurrence (new line text, or one more of
46726
+ * the same) surfaces. Identical repeated findings are matched by count.
46727
+ *
46728
+ * Diagnostics carrying `matchByOccurrence` (resolved at diagnostic creation:
46729
+ * every Accessibility-category finding, plus rules opting in via their
46730
+ * `matchByOccurrence` metadata flag) drop the line-text snippet and match by
46731
+ * `(filePath, plugin/rule)` occurrence count alone. Their identity is the
46732
+ * flagged element, not the line's text, so editing the line (reindentation,
46733
+ * prettier reflow, collapsing a multi-line JSX element) doesn't reclassify a
46734
+ * pre-existing finding as new — while one MORE occurrence of the same rule in
46735
+ * the file still surfaces. Expression-level rules keep the line-text snippet:
46736
+ * there the flagged expression IS the finding, so changed text means new +
46737
+ * fixed.
46738
+ *
46739
+ * v1 limitation: the fingerprint keys on the head-relative `filePath`, and base
46740
+ * content is read at that same path. A file renamed by the change therefore has
46741
+ * no base match, so its pre-existing findings are reported as new. This
46742
+ * over-reports (never hides a real issue) and is rare; rename-aware base
46743
+ * resolution is a follow-up.
46957
46744
  */
46958
46745
  const computeDiagnosticDelta = (input) => {
46959
- const baseCandidates = buildMatchCandidates(input.baseDiagnostics, input.readBaseEvidence, input.readBaseLine);
46960
- const headCandidates = buildMatchCandidates(input.headDiagnostics, input.readHeadEvidence, input.readHeadLine);
46961
- const baseByStableEvidence = /* @__PURE__ */ new Map();
46962
- const baseBySameFileStableEvidence = /* @__PURE__ */ new Map();
46963
- const baseBySameFileFallback = /* @__PURE__ */ new Map();
46964
- for (const candidate of baseCandidates) {
46965
- addDiagnosticIndex(baseByStableEvidence, candidate.stableEvidenceKey, candidate.diagnosticIndex);
46966
- addDiagnosticIndex(baseBySameFileStableEvidence, candidate.sameFileStableEvidenceKey, candidate.diagnosticIndex);
46967
- addDiagnosticIndex(baseBySameFileFallback, candidate.sameFileFallbackKey, candidate.diagnosticIndex);
46968
- }
46969
- const matchedHeadDiagnosticIndexes = /* @__PURE__ */ new Set();
46970
- const matchedBaseDiagnosticIndexes = /* @__PURE__ */ new Set();
46971
- const matchCandidates = (baseBuckets, getKey, onMatch) => {
46972
- for (const candidate of headCandidates) {
46973
- if (matchedHeadDiagnosticIndexes.has(candidate.diagnosticIndex)) continue;
46974
- const baseDiagnosticIndex = takeMatchingDiagnosticIndex(baseBuckets, getKey(candidate), matchedBaseDiagnosticIndexes);
46975
- if (baseDiagnosticIndex === null) continue;
46976
- matchedHeadDiagnosticIndexes.add(candidate.diagnosticIndex);
46977
- matchedBaseDiagnosticIndexes.add(baseDiagnosticIndex);
46978
- onMatch?.(candidate.diagnosticIndex, baseDiagnosticIndex);
46979
- }
46980
- };
46981
- matchCandidates(baseBySameFileStableEvidence, (candidate) => candidate.sameFileStableEvidenceKey);
46982
- matchCandidates(baseBySameFileFallback, (candidate) => candidate.sameFileFallbackKey);
46983
- let crossFileMatchCount = 0;
46984
- matchCandidates(baseByStableEvidence, (candidate) => candidate.stableEvidenceKey, (head, base) => {
46985
- if (input.headDiagnostics[head]?.filePath !== input.baseDiagnostics[base]?.filePath) crossFileMatchCount += 1;
46986
- });
46746
+ const unmatchedBaseByFingerprint = /* @__PURE__ */ new Map();
46747
+ for (const diagnostic of input.baseDiagnostics) {
46748
+ const key = fingerprintDiagnostic(diagnostic, input.readBaseLine(diagnostic.filePath, diagnostic.line));
46749
+ unmatchedBaseByFingerprint.set(key, (unmatchedBaseByFingerprint.get(key) ?? 0) + 1);
46750
+ }
46751
+ const newDiagnostics = [];
46752
+ for (const diagnostic of input.headDiagnostics) {
46753
+ const key = fingerprintDiagnostic(diagnostic, input.readHeadLine(diagnostic.filePath, diagnostic.line));
46754
+ const availableMatches = unmatchedBaseByFingerprint.get(key) ?? 0;
46755
+ if (availableMatches > 0) unmatchedBaseByFingerprint.set(key, availableMatches - 1);
46756
+ else newDiagnostics.push(diagnostic);
46757
+ }
46758
+ let fixedCount = 0;
46759
+ for (const remaining of unmatchedBaseByFingerprint.values()) fixedCount += remaining;
46987
46760
  return {
46988
- newDiagnostics: input.headDiagnostics.filter((_diagnostic, diagnosticIndex) => !matchedHeadDiagnosticIndexes.has(diagnosticIndex)),
46989
- fixedCount: input.baseDiagnostics.length - matchedBaseDiagnosticIndexes.size,
46990
- crossFileMatchCount
46761
+ newDiagnostics,
46762
+ fixedCount
46991
46763
  };
46992
46764
  };
46993
46765
  /**
@@ -47019,12 +46791,6 @@ const getDiffInfo = (directory, explicitBaseBranch, includeUntracked) => runProm
47019
46791
  };
47020
46792
  }).pipe(provide(Git.layerNode)));
47021
46793
  const filterSourceFiles = (filePaths) => filePaths.filter(isLintableSourceFile);
47022
- const getBaselineDiffPlan = (directory, ref) => runPromise(gen(function* () {
47023
- return yield* (yield* Git).baselineDiffPlan({
47024
- directory,
47025
- ref
47026
- });
47027
- }).pipe(provide(Git.layerNode)));
47028
46794
  /**
47029
46795
  * Programmatic façade over `Git.changedLineRanges` (the `lines` scope). Diffs
47030
46796
  * `files` with `--unified=0` against `baseRef` (or the index when `cached`),
@@ -47481,7 +47247,7 @@ const makeNoopConsole = () => ({
47481
47247
  });
47482
47248
  //#endregion
47483
47249
  //#region src/cli/utils/version.ts
47484
- const VERSION = "0.8.1-dev.61bf03e";
47250
+ const VERSION = "0.8.1-dev.7818922";
47485
47251
  //#endregion
47486
47252
  //#region src/cli/utils/json-mode.ts
47487
47253
  let context = null;
@@ -47833,13 +47599,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
47833
47599
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
47834
47600
  * standard `SENTRY_RELEASE` override.
47835
47601
  */
47836
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.61bf03e`;
47602
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.8.1-dev.7818922`;
47837
47603
  /**
47838
47604
  * Deployment environment shown in Sentry's environment filter. Defaults to
47839
47605
  * `production` for tagged releases and `development` for dev/unbuilt versions,
47840
47606
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
47841
47607
  */
47842
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.61bf03e") ? "development" : "production");
47608
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.8.1-dev.7818922") ? "development" : "production");
47843
47609
  /**
47844
47610
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
47845
47611
  * (set to `0` to disable tracing) and falls back to
@@ -60462,7 +60228,6 @@ const buildOutcomeAttributes = (input) => {
60462
60228
  new: summary.totalDiagnosticCount,
60463
60229
  fixed: result.baselineDelta.fixedCount,
60464
60230
  baseTotal: result.baselineDelta.baseTotalCount,
60465
- crossFileMatches: result.baselineDelta.crossFileMatchCount ?? null,
60466
60231
  degraded: false
60467
60232
  }));
60468
60233
  else if (input.gateExempt) attributes["baseline.degraded"] = true;
@@ -60576,49 +60341,28 @@ const diagnosticIntersectsLineRanges = (diagnostic, lineRanges) => {
60576
60341
  return lineRanges.some(([rangeStartLine, rangeEndLine]) => diagnostic.line <= rangeEndLine && diagnosticEndLine >= rangeStartLine);
60577
60342
  };
60578
60343
  //#endregion
60579
- //#region src/cli/utils/is-materializable-git-source.ts
60580
- const GIT_LFS_POINTER_HEADER = "version https://git-lfs.github.com/spec/v1";
60581
- const isMaterializableGitSource = (content) => !content.includes("\0") && !content.startsWith(GIT_LFS_POINTER_HEADER);
60582
- //#endregion
60583
60344
  //#region src/cli/utils/materialize-baseline-files.ts
60584
60345
  /**
60585
- * Materializes the base side of the `ref` → worktree diff into
60586
- * `tempDirectory`, mirroring the project layout plus head's config files so
60587
- * both sides lint under the same rules. Git rename heuristics are disabled by
60588
- * the diff planner, so an old path is retained as a base deletion while its
60589
- * new path is a head addition. Missing head-only additions are expected;
60590
- * missing paths that the plan says must exist at base make `isComplete` false.
60346
+ * Materializes the `ref` version of `files` into `tempDirectory` (via
60347
+ * `git show <ref>:<path>`), mirroring the project layout + head's config files
60348
+ * so the base lints under the same rules as head. Reuses the shared,
60349
+ * zip-slip-guarded `materializeSourceTree`. Per-file read misses (e.g. a file
60350
+ * the PR added, absent at base) are skipped, which is exactly what we want:
60351
+ * a brand-new file has no base counterpart, so all its findings are "new".
60591
60352
  */
60592
60353
  const materializeBaselineFiles = (input) => runPromise(gen(function* () {
60593
60354
  const git = yield* Git;
60594
- const diffPlan = yield* git.baselineDiffPlan({
60595
- directory: input.directory,
60596
- ref: input.ref
60597
- });
60598
- const baseFiles = input.baseFiles ?? diffPlan?.baseFiles;
60599
- const headFiles = input.headFiles ?? diffPlan?.headFiles;
60600
- const untrackedFiles = diffPlan?.untrackedFiles ?? [];
60601
- if (baseFiles === void 0 || headFiles === void 0) return null;
60602
- const files = [...new Set([...input.files, ...baseFiles])];
60603
- const tree = yield* materializeSourceTree({
60355
+ return yield* materializeSourceTree({
60604
60356
  directory: input.directory,
60605
- files,
60357
+ files: input.files,
60606
60358
  tempDirectory: input.tempDirectory,
60607
60359
  readContent: (relativePath) => git.showRefContent({
60608
60360
  directory: input.directory,
60609
60361
  ref: input.ref,
60610
60362
  relativePath,
60611
60363
  options: { maxBufferBytes: GIT_SHOW_MAX_BUFFER_BYTES }
60612
- }).pipe(map$3((content) => content !== null && isMaterializableGitSource(content) ? content : null))
60364
+ })
60613
60365
  });
60614
- const materializedFiles = new Set(tree.materializedFiles);
60615
- return {
60616
- ...tree,
60617
- baseFiles,
60618
- headFiles,
60619
- isComplete: baseFiles.every((filePath) => materializedFiles.has(filePath)),
60620
- untrackedFiles
60621
- };
60622
60366
  }).pipe(provide(Git.layerNode)));
60623
60367
  /**
60624
60368
  * Resolves the commit a baseline scan should read base content from — the
@@ -60641,8 +60385,8 @@ const resolveMergeBaseRef = async (directory, ref) => {
60641
60385
  //#region src/cli/utils/read-source-line.ts
60642
60386
  /**
60643
60387
  * Builds a cached `(filePath, line) -> source text` reader rooted at
60644
- * `rootDirectory`, used as the fallback when construct-level diagnostic
60645
- * evidence cannot be read. Wraps core's
60388
+ * `rootDirectory`, used to fingerprint a diagnostic by the content of its
60389
+ * flagged line (see `computeDiagnosticDelta`). Wraps core's
60646
60390
  * `createNodeReadFileLinesSync` with per-file memoization + 1-indexed line
60647
60391
  * lookup; unreadable files / out-of-range lines return `null`.
60648
60392
  */
@@ -60657,338 +60401,6 @@ const createSourceLineReader = (rootDirectory) => {
60657
60401
  };
60658
60402
  };
60659
60403
  //#endregion
60660
- //#region src/cli/utils/read-diagnostic-evidence.ts
60661
- const SOURCE_EXTENSIONS = [
60662
- ".ts",
60663
- ".tsx",
60664
- ".js",
60665
- ".jsx",
60666
- ".mts",
60667
- ".cts",
60668
- ".mjs",
60669
- ".cjs"
60670
- ];
60671
- const COMPONENT_WRAPPER_NAMES = new Set(["memo", "forwardRef"]);
60672
- const getScriptKind = (filePath) => {
60673
- const extension = path.extname(filePath).toLowerCase();
60674
- if (extension === ".tsx") return ts.ScriptKind.TSX;
60675
- if (extension === ".jsx") return ts.ScriptKind.JSX;
60676
- if (extension === ".js" || extension === ".mjs" || extension === ".cjs") return ts.ScriptKind.JS;
60677
- return ts.ScriptKind.TS;
60678
- };
60679
- const resolveSafeSourcePath = (rootDirectory, filePath) => {
60680
- try {
60681
- const resolvedRootDirectory = fs.realpathSync(rootDirectory);
60682
- const absolutePath = path.resolve(resolvedRootDirectory, filePath);
60683
- const relativePath = path.relative(resolvedRootDirectory, absolutePath);
60684
- if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath)) return null;
60685
- const stats = fs.lstatSync(absolutePath);
60686
- if (!stats.isFile() || stats.isSymbolicLink()) return null;
60687
- const realPath = fs.realpathSync(absolutePath);
60688
- const realRelativePath = path.relative(resolvedRootDirectory, realPath);
60689
- return realRelativePath !== ".." && !realRelativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(realRelativePath) ? realPath : null;
60690
- } catch {
60691
- return null;
60692
- }
60693
- };
60694
- const readSourceRecord = (rootDirectory, filePath, state) => {
60695
- const normalizedFilePath = filePath.replace(/\\/g, "/");
60696
- if (state.recordByFilePath.has(normalizedFilePath)) return state.recordByFilePath.get(normalizedFilePath) ?? null;
60697
- const absolutePath = resolveSafeSourcePath(rootDirectory, normalizedFilePath);
60698
- if (absolutePath === null) {
60699
- state.recordByFilePath.set(normalizedFilePath, null);
60700
- return null;
60701
- }
60702
- try {
60703
- const sourceText = fs.readFileSync(absolutePath, "utf-8");
60704
- const record = {
60705
- absolutePath,
60706
- filePath: normalizedFilePath,
60707
- sourceFile: ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(absolutePath)),
60708
- sourceText
60709
- };
60710
- state.recordByFilePath.set(normalizedFilePath, record);
60711
- return record;
60712
- } catch {
60713
- state.recordByFilePath.set(normalizedFilePath, null);
60714
- return null;
60715
- }
60716
- };
60717
- const listSourceRecords = (rootDirectory, state) => {
60718
- if (state.sourceRecords !== null) return state.sourceRecords;
60719
- state.sourceRecords = listSourceFiles(rootDirectory).flatMap((filePath) => {
60720
- const record = readSourceRecord(rootDirectory, filePath, state);
60721
- return record === null ? [] : [record];
60722
- });
60723
- return state.sourceRecords;
60724
- };
60725
- const unwrapExpression = (expression) => {
60726
- let currentExpression = expression;
60727
- while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression)) currentExpression = currentExpression.expression;
60728
- return currentExpression;
60729
- };
60730
- const getCalleeName = (expression) => {
60731
- const unwrappedExpression = unwrapExpression(expression);
60732
- if (ts.isIdentifier(unwrappedExpression)) return unwrappedExpression.text;
60733
- if (ts.isPropertyAccessExpression(unwrappedExpression)) return unwrappedExpression.name.text;
60734
- return null;
60735
- };
60736
- const isComponentWrapperCall = (node) => {
60737
- const wrapperName = getCalleeName(node.expression);
60738
- return wrapperName !== null && COMPONENT_WRAPPER_NAMES.has(wrapperName);
60739
- };
60740
- const getFunctionName = (node) => {
60741
- if (ts.isFunctionDeclaration(node) && node.name !== void 0) return node.name.text;
60742
- if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
60743
- let componentExpression = node;
60744
- while (true) {
60745
- const parent = componentExpression.parent;
60746
- if (ts.isParenthesizedExpression(parent) || ts.isAsExpression(parent) || ts.isTypeAssertionExpression(parent) || ts.isNonNullExpression(parent) || ts.isSatisfiesExpression(parent)) {
60747
- componentExpression = parent;
60748
- continue;
60749
- }
60750
- if (ts.isCallExpression(parent) && parent.arguments[0] === componentExpression && isComponentWrapperCall(parent)) {
60751
- componentExpression = parent;
60752
- continue;
60753
- }
60754
- if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) return parent.name.text;
60755
- return node.name?.text ?? null;
60756
- }
60757
- }
60758
- return null;
60759
- };
60760
- const isComponentFunction = (node) => ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node);
60761
- const isDefaultExportedComponent = (record, node, componentName) => {
60762
- if (ts.canHaveModifiers(node) && ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword)) return true;
60763
- return record.sourceFile.statements.some((statement) => ts.isExportAssignment(statement) && ts.isIdentifier(statement.expression) && statement.expression.text === componentName);
60764
- };
60765
- const findEnclosingComponent = (record, diagnostic) => {
60766
- if (!Number.isInteger(diagnostic.line) || diagnostic.line < 1) return null;
60767
- const lineIndex = diagnostic.line - 1;
60768
- const lineStarts = record.sourceFile.getLineStarts();
60769
- const lineStart = lineStarts[lineIndex];
60770
- if (lineStart === void 0) return null;
60771
- const nextLineStart = lineStarts[lineIndex + 1] ?? record.sourceFile.end;
60772
- const lineEnd = Math.max(lineStart, nextLineStart - 1);
60773
- const columnIndex = Number.isInteger(diagnostic.column) ? Math.max(0, diagnostic.column - 1) : 0;
60774
- const diagnosticPosition = Math.min(lineStart + columnIndex, lineEnd);
60775
- let component = null;
60776
- let componentWidth = Number.POSITIVE_INFINITY;
60777
- const visit = (node) => {
60778
- if (diagnosticPosition < node.getStart(record.sourceFile) || diagnosticPosition > node.end) return;
60779
- if (isComponentFunction(node)) {
60780
- const name = getFunctionName(node);
60781
- const width = node.end - node.getStart(record.sourceFile);
60782
- if (name !== null && /^[A-Z]/.test(name) && width < componentWidth) {
60783
- component = {
60784
- isDefaultExport: isDefaultExportedComponent(record, node, name),
60785
- name,
60786
- node,
60787
- record
60788
- };
60789
- componentWidth = width;
60790
- }
60791
- }
60792
- ts.forEachChild(node, visit);
60793
- };
60794
- visit(record.sourceFile);
60795
- return component;
60796
- };
60797
- const moduleSpecifierTargetsComponent = (callerRecord, moduleSpecifier, componentRecord) => {
60798
- if (!moduleSpecifier.startsWith(".")) return false;
60799
- const unresolvedPath = path.resolve(path.dirname(callerRecord.absolutePath), moduleSpecifier);
60800
- const specifiedExtension = path.extname(unresolvedPath).toLowerCase();
60801
- const sourcePathWithoutExtension = SOURCE_EXTENSIONS.includes(specifiedExtension) ? unresolvedPath.slice(0, -specifiedExtension.length) : unresolvedPath;
60802
- return [
60803
- unresolvedPath,
60804
- ...SOURCE_EXTENSIONS.map((extension) => `${sourcePathWithoutExtension}${extension}`),
60805
- ...sourcePathWithoutExtension === unresolvedPath ? SOURCE_EXTENSIONS.map((extension) => path.join(unresolvedPath, `index${extension}`)) : []
60806
- ].includes(componentRecord.absolutePath);
60807
- };
60808
- const getComponentTagNames = (record, component) => {
60809
- if (record.absolutePath === component.record.absolutePath) return new Set([component.name]);
60810
- const tagNames = /* @__PURE__ */ new Set();
60811
- for (const statement of record.sourceFile.statements) {
60812
- if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || !moduleSpecifierTargetsComponent(record, statement.moduleSpecifier.text, component.record)) continue;
60813
- const importClause = statement.importClause;
60814
- if (component.isDefaultExport && importClause?.name !== void 0) tagNames.add(importClause.name.text);
60815
- const namedBindings = importClause?.namedBindings;
60816
- if (namedBindings !== void 0 && ts.isNamedImports(namedBindings)) {
60817
- for (const element of namedBindings.elements) if ((element.propertyName?.text ?? element.name.text) === component.name) tagNames.add(element.name.text);
60818
- }
60819
- }
60820
- return tagNames;
60821
- };
60822
- const getTransparentCall = (functionNode) => {
60823
- if (functionNode.body === void 0) return null;
60824
- if (!ts.isBlock(functionNode.body)) {
60825
- const expression = unwrapExpression(functionNode.body);
60826
- return ts.isCallExpression(expression) ? expression : null;
60827
- }
60828
- if (functionNode.body.statements.length !== 1) return null;
60829
- const statement = functionNode.body.statements[0];
60830
- if (statement === void 0) return null;
60831
- const expression = ts.isExpressionStatement(statement) || ts.isReturnStatement(statement) ? statement.expression : void 0;
60832
- if (expression === void 0) return null;
60833
- const unwrappedExpression = unwrapExpression(expression);
60834
- return ts.isCallExpression(unwrappedExpression) ? unwrappedExpression : null;
60835
- };
60836
- const resolveTransparentTarget = (functionNode) => {
60837
- const call = getTransparentCall(functionNode);
60838
- if (call === null) return null;
60839
- const target = unwrapExpression(call.expression);
60840
- if (!ts.isIdentifier(target) || call.arguments.length !== functionNode.parameters.length) return null;
60841
- for (const [parameterIndex, parameter] of functionNode.parameters.entries()) {
60842
- const argument = call.arguments[parameterIndex];
60843
- const unwrappedArgument = argument === void 0 ? null : unwrapExpression(argument);
60844
- if (!ts.isIdentifier(parameter.name) || unwrappedArgument === null || !ts.isIdentifier(unwrappedArgument) || unwrappedArgument.text !== parameter.name.text) return null;
60845
- }
60846
- return target.text;
60847
- };
60848
- const getForwardingFunction = (declaration) => {
60849
- if (ts.isFunctionDeclaration(declaration)) return declaration;
60850
- if (!ts.isVariableDeclaration(declaration) || declaration.initializer === void 0) return null;
60851
- const initializer = unwrapExpression(declaration.initializer);
60852
- if (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) return initializer;
60853
- if (ts.isCallExpression(initializer) && getCalleeName(initializer.expression) === "useCallback") {
60854
- const callback = initializer.arguments[0];
60855
- if (callback !== void 0 && (ts.isArrowFunction(callback) || ts.isFunctionExpression(callback))) return callback;
60856
- }
60857
- return null;
60858
- };
60859
- const getDeclaredBindingName = (node) => {
60860
- if ((ts.isVariableDeclaration(node) || ts.isParameter(node) || ts.isBindingElement(node) || ts.isFunctionDeclaration(node)) && node.name !== void 0 && ts.isIdentifier(node.name)) return node.name.text;
60861
- if (ts.isImportClause(node)) return node.name?.text ?? null;
60862
- if (ts.isImportSpecifier(node) || ts.isNamespaceImport(node)) return node.name.text;
60863
- return null;
60864
- };
60865
- const findBindingScope = (node) => {
60866
- let currentNode = node;
60867
- while (currentNode !== void 0) {
60868
- if (ts.isParameter(currentNode) && ts.isFunctionLike(currentNode.parent)) return currentNode.parent;
60869
- if (ts.isBlock(currentNode) || ts.isModuleBlock(currentNode) || ts.isSourceFile(currentNode)) return currentNode;
60870
- currentNode = currentNode.parent;
60871
- }
60872
- return node.getSourceFile();
60873
- };
60874
- const findBindingDeclaration = (record, binding) => {
60875
- const usagePosition = binding.getStart(record.sourceFile);
60876
- const candidates = [];
60877
- const visit = (node) => {
60878
- if (getDeclaredBindingName(node) === binding.text) {
60879
- const scope = findBindingScope(node);
60880
- const isVisibleScope = usagePosition >= scope.getStart(record.sourceFile) && usagePosition <= scope.end;
60881
- const isVisibleDeclaration = ts.isFunctionDeclaration(node) || ts.isParameter(node) || ts.isBindingElement(node) || ts.isImportClause(node) || ts.isImportSpecifier(node) || ts.isNamespaceImport(node) || node.getStart(record.sourceFile) < usagePosition;
60882
- if (isVisibleScope && isVisibleDeclaration) candidates.push({
60883
- declaration: node,
60884
- scope
60885
- });
60886
- }
60887
- ts.forEachChild(node, visit);
60888
- };
60889
- visit(record.sourceFile);
60890
- let nearestCandidate = null;
60891
- let nearestScopeWidth = Number.POSITIVE_INFINITY;
60892
- let isNearestScopeAmbiguous = false;
60893
- for (const candidate of candidates) {
60894
- const scopeWidth = candidate.scope.end - candidate.scope.getStart(record.sourceFile);
60895
- if (scopeWidth < nearestScopeWidth) {
60896
- nearestCandidate = candidate;
60897
- nearestScopeWidth = scopeWidth;
60898
- isNearestScopeAmbiguous = false;
60899
- } else if (scopeWidth === nearestScopeWidth) isNearestScopeAmbiguous = true;
60900
- }
60901
- if (isNearestScopeAmbiguous) return null;
60902
- const declaration = nearestCandidate?.declaration;
60903
- return declaration !== void 0 && (ts.isVariableDeclaration(declaration) || ts.isFunctionDeclaration(declaration)) ? declaration : null;
60904
- };
60905
- const resolveHandlerBinding = (record, binding) => {
60906
- const declaration = findBindingDeclaration(record, binding);
60907
- if (declaration === null) return binding.text;
60908
- const forwardingFunction = getForwardingFunction(declaration);
60909
- const target = forwardingFunction === null ? null : resolveTransparentTarget(forwardingFunction);
60910
- return target === null || target === binding.text ? binding.text : target;
60911
- };
60912
- const getJsxTagName = (node) => ts.isIdentifier(node.tagName) ? node.tagName.text : null;
60913
- const getHandlerBinding = (node, propName) => {
60914
- for (const property of node.attributes.properties) {
60915
- if (!ts.isJsxAttribute(property) || property.name.getText() !== propName) continue;
60916
- const initializer = property.initializer;
60917
- if (initializer === void 0 || !ts.isJsxExpression(initializer)) return null;
60918
- if (initializer.expression === void 0) return null;
60919
- const expression = unwrapExpression(initializer.expression);
60920
- return ts.isIdentifier(expression) ? expression : null;
60921
- }
60922
- return null;
60923
- };
60924
- const getForwardedHandlerAliases = (rootDirectory, component, propNames, state) => {
60925
- const cacheKey = `${component.record.filePath}\0${component.name}\0${[...propNames].sort().join("\0")}`;
60926
- const cachedAliases = state.aliasesByComponent.get(cacheKey);
60927
- if (cachedAliases !== void 0) return cachedAliases;
60928
- const bindingsByPropName = /* @__PURE__ */ new Map();
60929
- const unresolvedPropNames = /* @__PURE__ */ new Set();
60930
- let callsiteCount = 0;
60931
- for (const record of listSourceRecords(rootDirectory, state)) {
60932
- const tagNames = getComponentTagNames(record, component);
60933
- if (tagNames.size === 0) continue;
60934
- const visit = (node) => {
60935
- if (record === component.record && node === component.node) return;
60936
- if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
60937
- const tagName = getJsxTagName(node);
60938
- if (tagName !== null && tagNames.has(tagName)) {
60939
- callsiteCount += 1;
60940
- for (const propName of propNames) {
60941
- const binding = getHandlerBinding(node, propName);
60942
- if (binding === null) {
60943
- unresolvedPropNames.add(propName);
60944
- continue;
60945
- }
60946
- const bindings = bindingsByPropName.get(propName) ?? /* @__PURE__ */ new Set();
60947
- bindings.add(resolveHandlerBinding(record, binding));
60948
- bindingsByPropName.set(propName, bindings);
60949
- }
60950
- }
60951
- }
60952
- ts.forEachChild(node, visit);
60953
- };
60954
- visit(record.sourceFile);
60955
- }
60956
- const aliases = /* @__PURE__ */ new Map();
60957
- if (callsiteCount > 0) for (const [propName, bindings] of bindingsByPropName) {
60958
- if (bindings.size !== 1 || unresolvedPropNames.has(propName)) continue;
60959
- const [bindingName] = bindings;
60960
- if (bindingName !== void 0) aliases.set(propName, bindingName);
60961
- }
60962
- state.aliasesByComponent.set(cacheKey, aliases);
60963
- return aliases;
60964
- };
60965
- const normalizeForwardedHandlers = (evidence, aliases) => {
60966
- let normalizedEvidence = evidence;
60967
- for (const [propName, bindingName] of aliases) normalizedEvidence = normalizedEvidence.replace(new RegExp(`\\{\\s*${propName}\\s*\\}`, "g"), `{${bindingName}}`).replace(new RegExp(`=>\\s*${propName}\\s*\\(`, "g"), `=> ${bindingName}(`);
60968
- return normalizedEvidence;
60969
- };
60970
- const createDiagnosticEvidenceReader = (rootDirectory, options = {}) => {
60971
- const state = {
60972
- aliasesByComponent: /* @__PURE__ */ new Map(),
60973
- recordByFilePath: /* @__PURE__ */ new Map(),
60974
- sourceRecords: null
60975
- };
60976
- return (diagnostic) => {
60977
- const record = readSourceRecord(rootDirectory, diagnostic.filePath, state);
60978
- if (record === null || !Number.isInteger(diagnostic.line)) return null;
60979
- const sourceLines = record.sourceText.split(/\r?\n/);
60980
- const startLineIndex = Math.max(0, diagnostic.line - 1);
60981
- const endLineIndex = Math.max(startLineIndex, (diagnostic.endLine ?? diagnostic.line) - 1);
60982
- const evidence = sourceLines.slice(startLineIndex, endLineIndex + 1).join("\n");
60983
- if (!options.resolveForwardedHandlers) return evidence;
60984
- const propNames = new Set(evidence.match(/\bon[A-Z]\w*\b/g) ?? []);
60985
- if (propNames.size === 0) return evidence;
60986
- const component = findEnclosingComponent(record, diagnostic);
60987
- if (component === null) return evidence;
60988
- return normalizeForwardedHandlers(evidence, getForwardedHandlerAliases(rootDirectory, component, propNames, state));
60989
- };
60990
- };
60991
- //#endregion
60992
60404
  //#region src/cli/utils/build-no-score-message.ts
60993
60405
  const ENTERPRISE_CONTACT_HINT = `Want something custom to your company? Contact us at ${ENTERPRISE_CONTACT_URL}.`;
60994
60406
  const buildNoScoreMessage = (isScoreDisabled) => {
@@ -62232,8 +61644,6 @@ const runBaselineComparison = async (params) => {
62232
61644
  directory: params.directory,
62233
61645
  ref: params.baselineRef,
62234
61646
  files: params.options.includePaths,
62235
- baseFiles: params.baseFiles,
62236
- headFiles: params.headFiles,
62237
61647
  tempDirectory
62238
61648
  }).catch((error) => {
62239
61649
  rmSync(tempDirectory, {
@@ -62242,24 +61652,7 @@ const runBaselineComparison = async (params) => {
62242
61652
  });
62243
61653
  throw error;
62244
61654
  });
62245
- if (snapshot === null) {
62246
- rmSync(tempDirectory, {
62247
- recursive: true,
62248
- force: true
62249
- });
62250
- return null;
62251
- }
62252
61655
  try {
62253
- if (!snapshot.isComplete) return null;
62254
- const analyzedHeadFiles = new Set(params.headAnalyzedFiles.map(toForwardSlashes));
62255
- const baseFiles = new Set(snapshot.baseFiles.map(toForwardSlashes));
62256
- const trackedHeadFiles = new Set(snapshot.headFiles.map(toForwardSlashes));
62257
- const expectedHeadFiles = new Set(trackedHeadFiles);
62258
- for (const filePath of params.options.includePaths) {
62259
- const normalizedFilePath = toForwardSlashes(filePath);
62260
- if (!baseFiles.has(normalizedFilePath)) expectedHeadFiles.add(normalizedFilePath);
62261
- }
62262
- if (filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
62263
61656
  const baseLayers = buildRuntimeLayers({
62264
61657
  directory: snapshot.tempDirectory,
62265
61658
  hasConfigOverride: true,
@@ -62275,7 +61668,7 @@ const runBaselineComparison = async (params) => {
62275
61668
  });
62276
61669
  const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
62277
61670
  directory: snapshot.tempDirectory,
62278
- includePaths: snapshot.materializedFiles,
61671
+ includePaths: params.options.includePaths,
62279
61672
  customRulesOnly: params.options.customRulesOnly,
62280
61673
  respectInlineDisables: params.options.respectInlineDisables,
62281
61674
  warnings: params.options.warnings,
@@ -62292,22 +61685,18 @@ const runBaselineComparison = async (params) => {
62292
61685
  deadlineEpochMs: params.deadlineEpochMs ?? void 0
62293
61686
  }, {}).pipe(provide(baseLayers), provideService$2(PerFileLintCacheEnabled, false), provideService$2(SidecarLintCacheEnabled, false), provideService$2(Console, silentConsole))));
62294
61687
  if (baseOutput.didLintFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
62295
- const hasUnscannedUntrackedSourceFiles = filterSourceFiles(snapshot.untrackedFiles.map(toForwardSlashes)).some((filePath) => !analyzedHeadFiles.has(filePath));
62296
61688
  const delta = computeDiagnosticDelta({
62297
61689
  headDiagnostics: params.headDiagnostics,
62298
61690
  baseDiagnostics: baseOutput.diagnostics,
62299
61691
  readHeadLine: createSourceLineReader(params.directory),
62300
- readBaseLine: createSourceLineReader(snapshot.tempDirectory),
62301
- readHeadEvidence: createDiagnosticEvidenceReader(params.directory, { resolveForwardedHandlers: true }),
62302
- readBaseEvidence: createDiagnosticEvidenceReader(snapshot.tempDirectory)
61692
+ readBaseLine: createSourceLineReader(snapshot.tempDirectory)
62303
61693
  });
62304
61694
  return {
62305
61695
  displayDiagnostics: delta.newDiagnostics,
62306
61696
  baselineDelta: {
62307
61697
  baseRef: params.baselineRef,
62308
- fixedCount: hasUnscannedUntrackedSourceFiles ? 0 : delta.fixedCount,
62309
- baseTotalCount: baseOutput.diagnostics.length,
62310
- crossFileMatchCount: delta.crossFileMatchCount
61698
+ fixedCount: delta.fixedCount,
61699
+ baseTotalCount: baseOutput.diagnostics.length
62311
61700
  }
62312
61701
  };
62313
61702
  } finally {
@@ -62414,9 +61803,6 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
62414
61803
  headDiagnostics: output.diagnostics,
62415
61804
  resolvedNodeBinaryPath,
62416
61805
  baselineRef: options.baseline.ref,
62417
- baseFiles: options.baseline.baseFiles,
62418
- headFiles: options.baseline.headFiles,
62419
- headAnalyzedFiles: output.analyzedFiles,
62420
61806
  deadlineEpochMs
62421
61807
  });
62422
61808
  if (comparison) {
@@ -64701,25 +64087,20 @@ const resolveProjectRelativeDirectory = (rootDirectory, projectDirectory) => {
64701
64087
  return relativeProjectDirectory;
64702
64088
  };
64703
64089
  //#endregion
64704
- //#region src/cli/utils/resolve-project-source-file-paths.ts
64705
- const resolveProjectSourceFilePaths = (rootDirectory, projectDirectory, filePaths) => {
64090
+ //#region src/cli/utils/resolve-project-diff-include-paths.ts
64091
+ const resolveProjectDiffIncludePaths = (rootDirectory, projectDirectory, diffInfo) => {
64706
64092
  const relativeProjectDirectory = resolveProjectRelativeDirectory(rootDirectory, projectDirectory);
64707
64093
  if (relativeProjectDirectory === null) return [];
64708
- const sourceFilePaths = filterSourceFiles([...filePaths]);
64709
- if (relativeProjectDirectory.length === 0) return sourceFilePaths;
64094
+ const changedSourceFiles = filterSourceFiles(diffInfo.changedFiles);
64095
+ if (relativeProjectDirectory.length === 0) return changedSourceFiles;
64710
64096
  const projectPrefix = `${relativeProjectDirectory}/`;
64711
- return sourceFilePaths.flatMap((filePath) => {
64097
+ return changedSourceFiles.flatMap((filePath) => {
64712
64098
  const normalizedFilePath = toForwardSlashes(filePath);
64713
64099
  if (!normalizedFilePath.startsWith(projectPrefix)) return [];
64714
64100
  const projectRelativePath = normalizedFilePath.slice(projectPrefix.length);
64715
64101
  return projectRelativePath.length > 0 ? [projectRelativePath] : [];
64716
64102
  });
64717
64103
  };
64718
- //#endregion
64719
- //#region src/cli/utils/resolve-project-diff-include-paths.ts
64720
- const resolveProjectDiffIncludePaths = (rootDirectory, projectDirectory, diffInfo) => {
64721
- return resolveProjectSourceFilePaths(rootDirectory, projectDirectory, diffInfo.changedFiles);
64722
- };
64723
64104
  /**
64724
64105
  * Re-keys repo-relative changed line ranges (from `getChangedLineRanges`) to
64725
64106
  * the scanned project, mirroring `resolveProjectDiffIncludePaths`'s boundary
@@ -65258,7 +64639,6 @@ const inspectAction = async (directory, flags) => {
65258
64639
  const isDiffMode = scope !== "full";
65259
64640
  const comparisonBaseRef = isDiffMode && diffInfo && !diffInfo.isCurrentChanges ? diffInfo.baseSha ? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseSha) : diffInfo.diffBaseRef ?? await resolveMergeBaseRef(resolvedDirectory, diffInfo.baseBranch) : null;
65260
64641
  const baselineRef = scope === "changed" ? comparisonBaseRef : null;
65261
- const baselineDiffPlan = baselineRef === null ? null : await getBaselineDiffPlan(resolvedDirectory, baselineRef);
65262
64642
  const linesBaseRef = diffInfo?.isCurrentChanges ? "HEAD" : comparisonBaseRef;
65263
64643
  const changedLineRanges = scope === "lines" && diffInfo !== null && (diffInfo.isCurrentChanges || linesBaseRef !== null) && diffInfo !== null ? await getChangedLineRanges({
65264
64644
  directory: resolvedDirectory,
@@ -65289,13 +64669,10 @@ const inspectAction = async (directory, flags) => {
65289
64669
  const supplyChainEnabled = flags.supplyChain ?? projectConfig?.supplyChain?.enabled !== false;
65290
64670
  let includePaths;
65291
64671
  let supplyChainManifestChanged = false;
65292
- const projectBaselineBaseFiles = baselineDiffPlan === null ? null : resolveProjectSourceFilePaths(resolvedDirectory, scanDirectory, baselineDiffPlan.baseFiles);
65293
- const projectBaselineHeadFiles = baselineDiffPlan === null ? null : resolveProjectSourceFilePaths(resolvedDirectory, scanDirectory, baselineDiffPlan.headFiles);
65294
64672
  if (isDiffMode) {
65295
64673
  const changedSourceFiles = diffInfo === null ? [] : resolveProjectDiffIncludePaths(resolvedDirectory, scanDirectory, diffInfo);
65296
64674
  supplyChainManifestChanged = supplyChainEnabled && diffInfo !== null && projectManifestChanged(resolvedDirectory, scanDirectory, diffInfo);
65297
- const hasBaselineOnlyFiles = (projectBaselineBaseFiles?.length ?? 0) > 0;
65298
- if (changedSourceFiles.length === 0 && !supplyChainManifestChanged && !hasBaselineOnlyFiles) {
64675
+ if (changedSourceFiles.length === 0 && !supplyChainManifestChanged) {
65299
64676
  if (!isQuiet) {
65300
64677
  cliLogger.dim(`No changed source files in ${scanDirectory}, skipping.`);
65301
64678
  cliLogger.break();
@@ -65303,7 +64680,6 @@ const inspectAction = async (directory, flags) => {
65303
64680
  return null;
65304
64681
  }
65305
64682
  includePaths = [...changedSourceFiles];
65306
- if (includePaths.length === 0 && hasBaselineOnlyFiles) includePaths.push(...projectBaselineBaseFiles ?? []);
65307
64683
  if (supplyChainManifestChanged) includePaths.push("package.json");
65308
64684
  }
65309
64685
  if (!isQuiet && !isMultiProject) cliLogger.dim(" ");
@@ -65315,11 +64691,7 @@ const inspectAction = async (directory, flags) => {
65315
64691
  configSourceDirectory: projectConfigSourceDirectory ?? void 0,
65316
64692
  suppressRendering: isMultiProject,
65317
64693
  concurrentScan: isMultiProject,
65318
- baseline: baselineRef !== null && projectBaselineBaseFiles !== null && projectBaselineHeadFiles !== null ? {
65319
- ref: baselineRef,
65320
- baseFiles: projectBaselineBaseFiles,
65321
- headFiles: projectBaselineHeadFiles
65322
- } : void 0,
64694
+ baseline: baselineRef ? { ref: baselineRef } : void 0,
65323
64695
  changedLineRanges: scope === "lines" && changedLineRanges !== null ? resolveProjectChangedLineRanges(resolvedDirectory, scanDirectory, changedLineRanges) : void 0,
65324
64696
  supplyChainManifestChanged
65325
64697
  });
@@ -66519,4 +65891,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
66519
65891
  export {};
66520
65892
 
66521
65893
  //# sourceMappingURL=cli.js.map
66522
- //# debugId=c5ad9312-01de-535b-a900-0d45e296a4fa
65894
+ //# debugId=9e32582f-b296-5216-a028-7cc19ed83931