react-doctor 0.9.1-dev.7ee59d3 → 0.9.1-dev.80e89c5

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 (4) hide show
  1. package/dist/cli.js +170 -72
  2. package/dist/index.js +167 -69
  3. package/dist/lsp.js +167 -69
  4. package/package.json +5 -4
package/dist/lsp.js CHANGED
@@ -10,6 +10,7 @@ import * as Crypto from "node:crypto";
10
10
  import crypto, { createHash } from "node:crypto";
11
11
  import * as NodeChildProcess from "node:child_process";
12
12
  import { execFileSync, spawn, spawnSync } from "node:child_process";
13
+ import { ResolverFactory } from "oxc-resolver";
13
14
  import ts from "typescript";
14
15
  import { parseJSON5 } from "confbox";
15
16
  import * as NodeUrl from "node:url";
@@ -62095,8 +62096,13 @@ const findMonorepoRoot = (startDirectory) => {
62095
62096
  * byte-equivalent copy.
62096
62097
  */
62097
62098
  const isProjectBoundary = (directory) => NFS.existsSync(Path.join(directory, ".git")) || isMonorepoRoot(directory);
62099
+ const unwrapTypescriptExpression = (expression) => {
62100
+ let currentExpression = expression;
62101
+ while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
62102
+ return currentExpression;
62103
+ };
62098
62104
  const TSCONFIG_FILENAME = "tsconfig.json";
62099
- const isRelativeExtendsValue = (extendsValue) => extendsValue.startsWith("./") || extendsValue.startsWith("../") || Path.isAbsolute(extendsValue);
62105
+ const isLocalModuleSpecifier = (moduleSpecifier) => moduleSpecifier === "." || moduleSpecifier === ".." || moduleSpecifier.startsWith("./") || moduleSpecifier.startsWith("../") || Path.isAbsolute(moduleSpecifier);
62100
62106
  const ensureJsonExtension = (filePath) => Path.extname(filePath) === "" ? `${filePath}.json` : filePath;
62101
62107
  const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
62102
62108
  const requireFromConfig = createRequire(Path.join(fromConfigDirectory, "tsconfig.json"));
@@ -62113,7 +62119,12 @@ const resolvePackageExtendsPath = (extendsValue, fromConfigDirectory) => {
62113
62119
  return null;
62114
62120
  };
62115
62121
  const resolveExtendsPath = (extendsValue, fromConfigDirectory) => {
62116
- if (isRelativeExtendsValue(extendsValue)) return ensureJsonExtension(Path.resolve(fromConfigDirectory, extendsValue));
62122
+ if (isLocalModuleSpecifier(extendsValue)) {
62123
+ const resolvedPath = Path.resolve(fromConfigDirectory, extendsValue);
62124
+ if (isFile(resolvedPath)) return resolvedPath;
62125
+ const directoryConfigPath = Path.join(resolvedPath, TSCONFIG_FILENAME);
62126
+ return isFile(directoryConfigPath) ? directoryConfigPath : ensureJsonExtension(resolvedPath);
62127
+ }
62117
62128
  return resolvePackageExtendsPath(extendsValue, fromConfigDirectory);
62118
62129
  };
62119
62130
  const normalizeCompilerOptions = (compilerOptions) => {
@@ -62307,6 +62318,15 @@ const REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS = [
62307
62318
  ".cts",
62308
62319
  ".json"
62309
62320
  ];
62321
+ const REACT_COMPILER_CONFIG_RESOLVER = new ResolverFactory({
62322
+ conditionNames: [
62323
+ "import",
62324
+ "require",
62325
+ "node",
62326
+ "default"
62327
+ ],
62328
+ extensions: REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS
62329
+ });
62310
62330
  const STATIC_EXPORT_OUTPUT_PATTERN = /(?:^|[^.\w])["']?output["']?\s*:\s*["']export["']/m;
62311
62331
  const hasCompilerPackage = (packageJson, compilerPackages) => {
62312
62332
  const allDependencies = {
@@ -62330,6 +62350,18 @@ const hasCompilerPackageInAncestors = (directory, compilerPackages) => {
62330
62350
  return false;
62331
62351
  };
62332
62352
  const resolveImportedConfigFile = (fromFilePath, moduleSpecifier) => {
62353
+ if (!isLocalModuleSpecifier(moduleSpecifier)) {
62354
+ try {
62355
+ const resolvedPath = REACT_COMPILER_CONFIG_RESOLVER.resolveFileSync(fromFilePath, moduleSpecifier).path;
62356
+ if (resolvedPath && isFile(resolvedPath)) return resolvedPath;
62357
+ } catch {}
62358
+ try {
62359
+ const resolvedPath = createRequire(fromFilePath).resolve(moduleSpecifier);
62360
+ return isFile(resolvedPath) ? resolvedPath : null;
62361
+ } catch {
62362
+ return null;
62363
+ }
62364
+ }
62333
62365
  const unresolvedPath = Path.resolve(Path.dirname(fromFilePath), moduleSpecifier);
62334
62366
  const extension = Path.extname(unresolvedPath);
62335
62367
  return (extension ? [unresolvedPath, ...REACT_COMPILER_CONFIG_SOURCE_EXTENSIONS.map((sourceExtension) => `${unresolvedPath.slice(0, -extension.length)}${sourceExtension}`)] : [
@@ -62540,9 +62572,11 @@ const getAssignedPropertyInitializer = (identifier, propertyName) => {
62540
62572
  initializer: assignedInitializer
62541
62573
  };
62542
62574
  };
62543
- const getStaticConfigValueState = (expression, analysis) => {
62544
- let unwrappedExpression = expression;
62545
- while (ts.isParenthesizedExpression(unwrappedExpression) || ts.isAsExpression(unwrappedExpression) || ts.isTypeAssertionExpression(unwrappedExpression) || ts.isSatisfiesExpression(unwrappedExpression) || ts.isNonNullExpression(unwrappedExpression)) unwrappedExpression = unwrappedExpression.expression;
62575
+ const getStaticConfigValueState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
62576
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
62577
+ if (visitedExpressions.has(unwrappedExpression)) return null;
62578
+ const nextVisitedExpressions = new Set(visitedExpressions);
62579
+ nextVisitedExpressions.add(unwrappedExpression);
62546
62580
  if (unwrappedExpression.kind === ts.SyntaxKind.NullKeyword || ts.isIdentifier(unwrappedExpression) && unwrappedExpression.text === "undefined") return {
62547
62581
  isNullish: true,
62548
62582
  isTruthy: false
@@ -62558,31 +62592,31 @@ const getStaticConfigValueState = (expression, analysis) => {
62558
62592
  if (ts.isIdentifier(unwrappedExpression)) {
62559
62593
  if (analysis.localBindings.has(unwrappedExpression.text)) {
62560
62594
  const localInitializer = analysis.localBindings.get(unwrappedExpression.text);
62561
- return localInitializer ? getStaticConfigValueState(localInitializer, analysis) : null;
62595
+ return localInitializer ? getStaticConfigValueState(localInitializer, analysis, nextVisitedExpressions) : null;
62562
62596
  }
62563
62597
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
62564
- return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis) : null;
62598
+ return topLevelBinding && ts.isExpression(topLevelBinding) ? getStaticConfigValueState(topLevelBinding, analysis, nextVisitedExpressions) : null;
62565
62599
  }
62566
62600
  if (ts.isConditionalExpression(unwrappedExpression)) {
62567
- const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis);
62568
- if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis);
62569
- const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis);
62570
- const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis);
62601
+ const conditionState = getStaticConfigValueState(unwrappedExpression.condition, analysis, nextVisitedExpressions);
62602
+ if (conditionState !== null) return getStaticConfigValueState(conditionState.isTruthy ? unwrappedExpression.whenTrue : unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
62603
+ const whenTrueState = getStaticConfigValueState(unwrappedExpression.whenTrue, analysis, nextVisitedExpressions);
62604
+ const whenFalseState = getStaticConfigValueState(unwrappedExpression.whenFalse, analysis, nextVisitedExpressions);
62571
62605
  return whenTrueState !== null && whenFalseState !== null && whenTrueState.isNullish === whenFalseState.isNullish && whenTrueState.isTruthy === whenFalseState.isTruthy ? whenTrueState : null;
62572
62606
  }
62573
62607
  if (ts.isBinaryExpression(unwrappedExpression)) {
62574
- const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis);
62608
+ const leftState = getStaticConfigValueState(unwrappedExpression.left, analysis, nextVisitedExpressions);
62575
62609
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
62576
62610
  if (leftState === null) return null;
62577
- return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
62611
+ return leftState.isTruthy ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
62578
62612
  }
62579
62613
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
62580
62614
  if (leftState === null) return null;
62581
- return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis);
62615
+ return leftState.isTruthy ? leftState : getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions);
62582
62616
  }
62583
62617
  if (unwrappedExpression.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) {
62584
62618
  if (leftState === null) return null;
62585
- return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis) : leftState;
62619
+ return leftState.isNullish ? getStaticConfigValueState(unwrappedExpression.right, analysis, nextVisitedExpressions) : leftState;
62586
62620
  }
62587
62621
  }
62588
62622
  return null;
@@ -62591,25 +62625,27 @@ const isStaticallyDisabledConfigExpression = (expression, analysis) => getStatic
62591
62625
  const isStaticallyTruthyConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isTruthy === true;
62592
62626
  const isStaticallyNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === true;
62593
62627
  const isStaticallyNonNullishConfigExpression = (expression, analysis) => getStaticConfigValueState(expression, analysis)?.isNullish === false;
62594
- const getReactCompilerFlagState = (expression, analysis) => {
62595
- let unwrappedExpression = expression;
62596
- while (ts.isParenthesizedExpression(unwrappedExpression) || ts.isAsExpression(unwrappedExpression) || ts.isTypeAssertionExpression(unwrappedExpression) || ts.isSatisfiesExpression(unwrappedExpression) || ts.isNonNullExpression(unwrappedExpression)) unwrappedExpression = unwrappedExpression.expression;
62628
+ const getReactCompilerFlagState = (expression, analysis, visitedExpressions = /* @__PURE__ */ new Set()) => {
62629
+ const unwrappedExpression = unwrapTypescriptExpression(expression);
62630
+ if (visitedExpressions.has(unwrappedExpression)) return null;
62631
+ const nextVisitedExpressions = new Set(visitedExpressions);
62632
+ nextVisitedExpressions.add(unwrappedExpression);
62597
62633
  if (ts.isIdentifier(unwrappedExpression)) {
62598
62634
  const assignedBinding = getAssignedPropertyInitializer(unwrappedExpression, "reactCompiler");
62599
62635
  if (assignedBinding.wasFound && assignedBinding.initializer) return { isEnabled: !isStaticallyDisabledConfigExpression(assignedBinding.initializer, analysis) };
62600
62636
  if (analysis.localBindings.has(unwrappedExpression.text)) {
62601
62637
  const localInitializer = analysis.localBindings.get(unwrappedExpression.text);
62602
- return localInitializer ? getReactCompilerFlagState(localInitializer, analysis) : null;
62638
+ return localInitializer ? getReactCompilerFlagState(localInitializer, analysis, nextVisitedExpressions) : null;
62603
62639
  }
62604
62640
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, unwrappedExpression.text);
62605
- return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis) : null;
62641
+ return topLevelBinding && ts.isExpression(topLevelBinding) ? getReactCompilerFlagState(topLevelBinding, analysis, nextVisitedExpressions) : null;
62606
62642
  }
62607
62643
  if (!ts.isObjectLiteralExpression(unwrappedExpression)) return null;
62608
62644
  for (const property of [...unwrappedExpression.properties].reverse()) {
62609
62645
  if (ts.isPropertyAssignment(property) && getStaticPropertyName$2(property.name) === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.initializer, analysis) };
62610
62646
  if (ts.isShorthandPropertyAssignment(property) && property.name.text === "reactCompiler") return { isEnabled: !isStaticallyDisabledConfigExpression(property.name, analysis) };
62611
62647
  if (ts.isSpreadAssignment(property)) {
62612
- const spreadState = getReactCompilerFlagState(property.expression, analysis);
62648
+ const spreadState = getReactCompilerFlagState(property.expression, analysis, nextVisitedExpressions);
62613
62649
  if (spreadState) return spreadState;
62614
62650
  }
62615
62651
  }
@@ -62781,6 +62817,11 @@ const analyzeConfigFunction = (functionNode, analysis, allowCompilerTransform, a
62781
62817
  visitReturns(functionNode.body);
62782
62818
  return hasCompiler;
62783
62819
  };
62820
+ const analyzeImportedConfig = ({ analysis, moduleSpecifier, exportName, allowCompilerTransform, argumentsList }) => {
62821
+ const importedFilePath = resolveImportedConfigFile(analysis.filePath, moduleSpecifier);
62822
+ if (!importedFilePath) return null;
62823
+ return analyzeConfigModuleExport(importedFilePath, exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, argumentsList);
62824
+ };
62784
62825
  const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, isCompilerTransformCollection, excludedPropertyNames) => {
62785
62826
  const assignedReactCompiler = getAssignedPropertyInitializer(identifier, "reactCompiler");
62786
62827
  if (assignedReactCompiler.initializer && !isStaticallyDisabledConfigExpression(assignedReactCompiler.initializer, analysis)) return true;
@@ -62801,30 +62842,62 @@ const analyzeConfigIdentifier = (identifier, analysis, allowCompilerTransform, i
62801
62842
  const importBinding = getImportBinding(analysis.sourceFile, identifier.text);
62802
62843
  if (importBinding) {
62803
62844
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
62804
- if (!importBinding.moduleSpecifier.startsWith(".")) return false;
62805
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62806
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
62845
+ return Boolean(analyzeImportedConfig({
62846
+ analysis,
62847
+ moduleSpecifier: importBinding.moduleSpecifier,
62848
+ exportName: importBinding.exportName,
62849
+ allowCompilerTransform
62850
+ }));
62807
62851
  }
62808
62852
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, identifier.text);
62809
62853
  return Boolean(topLevelBinding && analyzeConfigNode(topLevelBinding, analysis, allowCompilerTransform, isCompilerTransformCollection, overriddenPropertyNames));
62810
62854
  };
62811
62855
  const analyzeConfigCallTarget = (callExpression, analysis, allowCompilerTransform) => {
62812
62856
  const target = callExpression.expression;
62857
+ const callableRequiredModuleSpecifier = getRequireModuleSpecifier$1(target);
62858
+ if (callableRequiredModuleSpecifier !== null) {
62859
+ if (ts.isCallExpression(target) && ts.isIdentifier(target.expression) && (analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62860
+ if (allowCompilerTransform && isCompilerTransformModule(callableRequiredModuleSpecifier, "default")) return true;
62861
+ const hasCompilerTransform = analyzeImportedConfig({
62862
+ analysis,
62863
+ moduleSpecifier: callableRequiredModuleSpecifier,
62864
+ exportName: "default",
62865
+ allowCompilerTransform,
62866
+ argumentsList: callExpression.arguments
62867
+ });
62868
+ if (isLocalModuleSpecifier(callableRequiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
62869
+ return null;
62870
+ }
62813
62871
  if (!ts.isPropertyAccessExpression(target) && !ts.isElementAccessExpression(target)) return null;
62814
62872
  const propertyName = ts.isPropertyAccessExpression(target) ? target.name.text : target.argumentExpression && ts.isStringLiteralLike(target.argumentExpression) ? target.argumentExpression.text : null;
62815
62873
  if (propertyName === null) return null;
62816
62874
  const requiredModuleSpecifier = getRequireModuleSpecifier$1(target.expression);
62817
62875
  if (requiredModuleSpecifier !== null) {
62818
- if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62819
- if (!requiredModuleSpecifier.startsWith(".")) return null;
62820
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, requiredModuleSpecifier);
62821
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, propertyName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, callExpression.arguments));
62876
+ if (ts.isCallExpression(target.expression) && ts.isIdentifier(target.expression.expression) && (analysis.localBindings.has(target.expression.expression.text) || getScopedConfigBinding(target.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62877
+ if (allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, propertyName)) return true;
62878
+ const hasCompilerTransform = analyzeImportedConfig({
62879
+ analysis,
62880
+ moduleSpecifier: requiredModuleSpecifier,
62881
+ exportName: propertyName,
62882
+ allowCompilerTransform,
62883
+ argumentsList: callExpression.arguments
62884
+ });
62885
+ if (isLocalModuleSpecifier(requiredModuleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
62886
+ return null;
62822
62887
  }
62823
62888
  if (!ts.isIdentifier(target.expression)) return null;
62824
- const importBinding = getImportBinding(analysis.sourceFile, target.expression.text);
62825
- if (importBinding?.isNamespace && importBinding.moduleSpecifier.startsWith(".")) {
62826
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62827
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, propertyName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, callExpression.arguments));
62889
+ const importBinding = analysis.localBindings.has(target.expression.text) || getScopedConfigBinding(target.expression).wasFound ? null : getImportBinding(analysis.sourceFile, target.expression.text);
62890
+ if (importBinding?.isNamespace) {
62891
+ if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, propertyName)) return true;
62892
+ const hasCompilerTransform = analyzeImportedConfig({
62893
+ analysis,
62894
+ moduleSpecifier: importBinding.moduleSpecifier,
62895
+ exportName: propertyName,
62896
+ allowCompilerTransform,
62897
+ argumentsList: callExpression.arguments
62898
+ });
62899
+ if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
62900
+ return null;
62828
62901
  }
62829
62902
  const selectedProperty = getSelectedObjectProperty(target.expression, propertyName, analysis);
62830
62903
  if (selectedProperty === null) return null;
@@ -62847,9 +62920,13 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62847
62920
  if (propertyName === "reactCompiler") continue;
62848
62921
  if ((propertyName === "plugins" || propertyName === "presets") && node.properties.slice(propertyIndex + 1).some((laterProperty) => ts.isSpreadAssignment(laterProperty) && configExpressionMayDefineProperty(laterProperty.expression, propertyName, analysis) || (ts.isPropertyAssignment(laterProperty) || ts.isShorthandPropertyAssignment(laterProperty)) && getStaticPropertyName$2(laterProperty.name) === propertyName)) continue;
62849
62922
  const propertyAllowsCompilerTransform = propertyName === "plugins" || propertyName === "presets";
62850
- if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer) && property.initializer.text.startsWith(".")) {
62851
- const extendedFilePath = resolveImportedConfigFile(analysis.filePath, property.initializer.text);
62852
- if (extendedFilePath && analyzeConfigModuleExport(extendedFilePath, "default", false, analysis.importDepth + 1, analysis.visitedModules)) return true;
62923
+ if (propertyName === "extends" && ts.isStringLiteralLike(property.initializer)) {
62924
+ if (analyzeImportedConfig({
62925
+ analysis,
62926
+ moduleSpecifier: property.initializer.text,
62927
+ exportName: "default",
62928
+ allowCompilerTransform: false
62929
+ })) return true;
62853
62930
  }
62854
62931
  if (analyzeConfigNode(property.initializer, analysis, propertyAllowsCompilerTransform, propertyAllowsCompilerTransform)) return true;
62855
62932
  } else if (ts.isShorthandPropertyAssignment(property)) {
@@ -62882,16 +62959,27 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62882
62959
  if (directModuleSpecifier && isRequireShadowed) return analyzeConfigNode(node.expression, analysis, allowCompilerTransform);
62883
62960
  if (directModuleSpecifier && !isRequireShadowed) {
62884
62961
  if (allowCompilerTransform && isCompilerTransformModule(directModuleSpecifier, "default")) return true;
62885
- if (directModuleSpecifier.startsWith(".")) {
62886
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, directModuleSpecifier);
62887
- if (importedFilePath && analyzeConfigModuleExport(importedFilePath, "default", allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules)) return true;
62888
- }
62962
+ if (analyzeImportedConfig({
62963
+ analysis,
62964
+ moduleSpecifier: directModuleSpecifier,
62965
+ exportName: "default",
62966
+ allowCompilerTransform
62967
+ })) return true;
62889
62968
  }
62890
62969
  if (ts.isIdentifier(node.expression)) {
62891
- const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62892
- if (importBinding?.moduleSpecifier.startsWith(".")) {
62893
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62894
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, importBinding.exportName, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules, node.arguments));
62970
+ if (!analysis.localBindings.has(node.expression.text) && !getScopedConfigBinding(node.expression).wasFound) {
62971
+ const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62972
+ if (importBinding) {
62973
+ if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, importBinding.exportName)) return true;
62974
+ const hasCompilerTransform = analyzeImportedConfig({
62975
+ analysis,
62976
+ moduleSpecifier: importBinding.moduleSpecifier,
62977
+ exportName: importBinding.exportName,
62978
+ allowCompilerTransform,
62979
+ argumentsList: node.arguments
62980
+ });
62981
+ if (isLocalModuleSpecifier(importBinding.moduleSpecifier) || hasCompilerTransform !== null) return Boolean(hasCompilerTransform);
62982
+ }
62895
62983
  }
62896
62984
  const topLevelBinding = getTopLevelBinding(analysis.sourceFile, node.expression.text);
62897
62985
  if (topLevelBinding && ts.isFunctionLike(topLevelBinding) && analyzeConfigFunction(topLevelBinding, analysis, allowCompilerTransform, node.arguments)) return true;
@@ -62901,25 +62989,29 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62901
62989
  if (ts.isPropertyAccessExpression(node)) {
62902
62990
  const requiredModuleSpecifier = getRequireModuleSpecifier$1(node.expression);
62903
62991
  if (requiredModuleSpecifier) {
62904
- if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62905
- if (requiredModuleSpecifier.startsWith(".")) {
62906
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, requiredModuleSpecifier);
62907
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, node.name.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
62908
- }
62992
+ if (ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && (analysis.localBindings.has(node.expression.expression.text) || getScopedConfigBinding(node.expression.expression).wasFound || hasTopLevelValueBinding(analysis.sourceFile, "require"))) return false;
62993
+ if (analyzeImportedConfig({
62994
+ analysis,
62995
+ moduleSpecifier: requiredModuleSpecifier,
62996
+ exportName: node.name.text,
62997
+ allowCompilerTransform
62998
+ })) return true;
62909
62999
  return allowCompilerTransform && isCompilerTransformModule(requiredModuleSpecifier, node.name.text);
62910
63000
  }
62911
63001
  if (ts.isIdentifier(node.expression)) {
62912
- if (analysis.localBindings.has(node.expression.text)) {
62913
- const localInitializer = analysis.localBindings.get(node.expression.text);
62914
- return Boolean(localInitializer && analyzeConfigNode(localInitializer, analysis, allowCompilerTransform));
63002
+ if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
63003
+ const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
63004
+ return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
62915
63005
  }
62916
63006
  const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62917
63007
  if (importBinding?.isNamespace) {
62918
63008
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.name.text)) return true;
62919
- if (importBinding.moduleSpecifier.startsWith(".")) {
62920
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62921
- if (importedFilePath && analyzeConfigModuleExport(importedFilePath, node.name.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules)) return true;
62922
- }
63009
+ if (analyzeImportedConfig({
63010
+ analysis,
63011
+ moduleSpecifier: importBinding.moduleSpecifier,
63012
+ exportName: node.name.text,
63013
+ allowCompilerTransform
63014
+ })) return true;
62923
63015
  return false;
62924
63016
  }
62925
63017
  const selectedProperty = getSelectedObjectProperty(node.expression, node.name.text, analysis);
@@ -62930,13 +63022,19 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62930
63022
  }
62931
63023
  if (ts.isElementAccessExpression(node) && node.argumentExpression && ts.isStringLiteralLike(node.argumentExpression)) {
62932
63024
  if (ts.isIdentifier(node.expression)) {
63025
+ if (analysis.localBindings.has(node.expression.text) || getScopedConfigBinding(node.expression).wasFound) {
63026
+ const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
63027
+ return Boolean(selectedProperty && analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform));
63028
+ }
62933
63029
  const importBinding = getImportBinding(analysis.sourceFile, node.expression.text);
62934
63030
  if (importBinding?.isNamespace) {
62935
63031
  if (allowCompilerTransform && isCompilerTransformModule(importBinding.moduleSpecifier, node.argumentExpression.text)) return true;
62936
- if (importBinding.moduleSpecifier.startsWith(".")) {
62937
- const importedFilePath = resolveImportedConfigFile(analysis.filePath, importBinding.moduleSpecifier);
62938
- return Boolean(importedFilePath && analyzeConfigModuleExport(importedFilePath, node.argumentExpression.text, allowCompilerTransform, analysis.importDepth + 1, analysis.visitedModules));
62939
- }
63032
+ return Boolean(analyzeImportedConfig({
63033
+ analysis,
63034
+ moduleSpecifier: importBinding.moduleSpecifier,
63035
+ exportName: node.argumentExpression.text,
63036
+ allowCompilerTransform
63037
+ }));
62940
63038
  }
62941
63039
  const selectedProperty = getSelectedObjectProperty(node.expression, node.argumentExpression.text, analysis);
62942
63040
  if (selectedProperty) return analyzeConfigNode(selectedProperty, analysis, allowCompilerTransform);
@@ -62974,14 +63072,19 @@ const analyzeConfigNode = (node, analysis, allowCompilerTransform, isCompilerTra
62974
63072
  };
62975
63073
  const hasCompilerInConfigFile = (filePath) => analyzeConfigModuleExport(filePath, "default", false, 0, /* @__PURE__ */ new Set());
62976
63074
  const hasCompilerInConfigFiles = (directory, filenames) => filenames.some((filename) => hasCompilerInConfigFile(Path.join(directory, filename)));
62977
- const hasCompilerInPackageJsonConfig = (packageJson) => isPlainObject(packageJson.babel) && analyzeConfigSourceFileExport(ts.parseJsonText("package.json", JSON.stringify(packageJson.babel)), "package.json#babel", "default", false, 0, /* @__PURE__ */ new Set());
62978
- const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
63075
+ const hasCompilerInPackageJsonConfig = (directory, packageJson) => {
63076
+ if (!isPlainObject(packageJson.babel)) return false;
63077
+ const packageJsonPath = Path.join(directory, "package.json");
63078
+ return analyzeConfigSourceFileExport(ts.parseJsonText(packageJsonPath, JSON.stringify(packageJson.babel)), packageJsonPath, "default", false, 0, /* @__PURE__ */ new Set());
63079
+ };
63080
+ const hasCompilerConfiguration = (directory, packageJson) => hasCompilerInPackageJsonConfig(directory, packageJson) || hasCompilerInConfigFiles(directory, REACT_COMPILER_CONFIG_FILENAMES);
62979
63081
  const hasCompilerConfigurationInAncestors = (directory) => {
62980
63082
  if (isProjectBoundary(directory)) return false;
62981
63083
  let ancestorDirectory = Path.dirname(directory);
62982
63084
  while (ancestorDirectory !== Path.dirname(ancestorDirectory)) {
62983
63085
  const ancestorPackagePath = Path.join(ancestorDirectory, "package.json");
62984
- if (hasCompilerInPackageJsonConfig(isFile(ancestorPackagePath) ? readPackageJson(ancestorPackagePath) : {}) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
63086
+ const ancestorPackageJson = isFile(ancestorPackagePath) ? readPackageJson(ancestorPackagePath) : {};
63087
+ if (hasCompilerInPackageJsonConfig(ancestorDirectory, ancestorPackageJson) || hasCompilerInConfigFiles(ancestorDirectory, BABEL_CONFIG_FILENAMES)) return true;
62985
63088
  if (isProjectBoundary(ancestorDirectory)) return false;
62986
63089
  ancestorDirectory = Path.dirname(ancestorDirectory);
62987
63090
  }
@@ -67165,11 +67268,6 @@ const getTypescriptScriptKind = (fileName) => {
67165
67268
  if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
67166
67269
  return ts.ScriptKind.JS;
67167
67270
  };
67168
- const unwrapTypescriptExpression = (expression) => {
67169
- let currentExpression = expression;
67170
- while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
67171
- return currentExpression;
67172
- };
67173
67271
  const BABEL_CONFIG_FILE_NAMES$1 = [
67174
67272
  "babel.config.js",
67175
67273
  "babel.config.cjs",
@@ -76416,5 +76514,5 @@ const startLanguageServer = () => {
76416
76514
  };
76417
76515
  //#endregion
76418
76516
  export { startLanguageServer };
76419
- !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]="6a2a246a-da30-59c5-aa97-af8188206b96")}catch(e){}}();
76420
- //# debugId=6a2a246a-da30-59c5-aa97-af8188206b96
76517
+ !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]="48e73e9e-1848-53fc-a033-6e6aacd3c6c2")}catch(e){}}();
76518
+ //# debugId=48e73e9e-1848-53fc-a033-6e6aacd3c6c2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-doctor",
3
- "version": "0.9.1-dev.7ee59d3",
3
+ "version": "0.9.1-dev.80e89c5",
4
4
  "description": "Your agent writes bad React. This catches it",
5
5
  "keywords": [
6
6
  "accessibility",
@@ -61,6 +61,7 @@
61
61
  "ink-spinner": "^5.0.0",
62
62
  "jiti": "^2.7.0",
63
63
  "magicast": "^0.5.3",
64
+ "oxc-resolver": "^11.24.2",
64
65
  "oxlint": ">=1.74.0 <1.75.0",
65
66
  "prompts": "^2.4.2",
66
67
  "react": "19.2.5",
@@ -70,7 +71,7 @@
70
71
  "vscode-uri": "^3.1.0",
71
72
  "yaml": "^2.9.0",
72
73
  "deslop-js": "0.9.1",
73
- "oxlint-plugin-react-doctor": "0.9.1-dev.7ee59d3"
74
+ "oxlint-plugin-react-doctor": "0.9.1-dev.80e89c5"
74
75
  },
75
76
  "devDependencies": {
76
77
  "@types/babel__code-frame": "^7.27.0",
@@ -81,8 +82,8 @@
81
82
  "ink-testing-library": "^4.0.0",
82
83
  "ora": "^9.4.0",
83
84
  "@react-doctor/api": "0.9.1",
84
- "@react-doctor/core": "0.9.1",
85
- "@react-doctor/language-server": "0.9.1"
85
+ "@react-doctor/language-server": "0.9.1",
86
+ "@react-doctor/core": "0.9.1"
86
87
  },
87
88
  "engines": {
88
89
  "node": "^20.19.0 || >=22.13.0"