react-doctor 0.7.7-dev.bdd1321 → 0.7.7-dev.ce4179b
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 +427 -69
- package/dist/index.js +424 -66
- package/dist/lsp.js +424 -66
- package/dist/skills/improve-react/AUDIT.md +140 -0
- package/dist/skills/improve-react/PLAN-TEMPLATE.md +82 -0
- package/dist/skills/improve-react/SKILL.md +121 -0
- package/package.json +3 -3
package/dist/lsp.js
CHANGED
|
@@ -37160,18 +37160,45 @@ const checkReactServerComponentsAdvisory = (scanDirectory, project) => {
|
|
|
37160
37160
|
}
|
|
37161
37161
|
return diagnostics;
|
|
37162
37162
|
};
|
|
37163
|
-
const
|
|
37164
|
-
|
|
37165
|
-
|
|
37163
|
+
const getTypescriptScriptKind = (fileName) => {
|
|
37164
|
+
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
37165
|
+
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
37166
|
+
if (fileName.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
37167
|
+
return ts.ScriptKind.JS;
|
|
37168
|
+
};
|
|
37169
|
+
const unwrapTypescriptExpression = (expression) => {
|
|
37170
|
+
let currentExpression = expression;
|
|
37171
|
+
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
37172
|
+
return currentExpression;
|
|
37173
|
+
};
|
|
37174
|
+
const EMPTY_MOTION_EXPRESSION_EVIDENCE = {
|
|
37175
|
+
isAnimationFunction: false,
|
|
37176
|
+
isMotionComponent: false,
|
|
37177
|
+
isMotionComponentFactory: false,
|
|
37178
|
+
isMotionComponentNamespace: false,
|
|
37179
|
+
isMotionConfig: false,
|
|
37180
|
+
isMotionNamespace: false,
|
|
37181
|
+
isReducedMotionHook: false
|
|
37182
|
+
};
|
|
37183
|
+
const MOTION_COMPONENT_FACTORY_EXPORT_NAMES = new Set(["m", "motion"]);
|
|
37184
|
+
const MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES = new Set(["Reorder"]);
|
|
37185
|
+
const MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES = new Set(["Item"]);
|
|
37186
|
+
const MOTION_ANIMATION_FUNCTION_EXPORT_NAMES = new Set(["animate"]);
|
|
37187
|
+
const REDUCED_MOTION_HOOK_EXPORT_NAME = "useReducedMotion";
|
|
37188
|
+
const MOTION_CONFIG_EXPORT_NAME = "MotionConfig";
|
|
37189
|
+
const REDUCED_MOTION_PROP_NAME = "reducedMotion";
|
|
37190
|
+
const REDUCED_MOTION_CONFIG_VALUES = new Set(["always", "user"]);
|
|
37191
|
+
const SCRIPT_MODULE_EXTENSIONS = [
|
|
37166
37192
|
".ts",
|
|
37167
37193
|
".tsx",
|
|
37168
37194
|
".js",
|
|
37169
|
-
".jsx"
|
|
37170
|
-
|
|
37171
|
-
|
|
37172
|
-
]);
|
|
37173
|
-
const
|
|
37174
|
-
const
|
|
37195
|
+
".jsx"
|
|
37196
|
+
];
|
|
37197
|
+
const SCRIPT_FILE_EXTENSIONS = new Set(SCRIPT_MODULE_EXTENSIONS);
|
|
37198
|
+
const STYLE_FILE_EXTENSIONS = new Set([".css", ".scss"]);
|
|
37199
|
+
const MOTION_SOURCE_PREFILTER = /framer-motion|["']motion(?:\/[A-Za-z0-9_./-]+)?["']|MotionConfig|useReducedMotion/;
|
|
37200
|
+
const REDUCED_MOTION_MEDIA_QUERY_PATTERN = /@media\s+([^{}]*\(\s*prefers-reduced-motion\s*:\s*reduce\s*\)[^{}]*)\{/gi;
|
|
37201
|
+
const CSS_DECLARATION_PATTERN = /(?:^|[;{])\s*[-_A-Za-z][-_A-Za-z0-9]*\s*:/;
|
|
37175
37202
|
const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
37176
37203
|
filePath: "package.json",
|
|
37177
37204
|
plugin: "react-doctor",
|
|
@@ -37183,52 +37210,406 @@ const MISSING_REDUCED_MOTION_DIAGNOSTIC = {
|
|
|
37183
37210
|
column: 0,
|
|
37184
37211
|
category: "Accessibility"
|
|
37185
37212
|
};
|
|
37186
|
-
const
|
|
37213
|
+
const isMotionModuleSource = (moduleSource) => {
|
|
37214
|
+
for (const packageName of MOTION_LIBRARY_PACKAGES) if (moduleSource === packageName || moduleSource.startsWith(`${packageName}/`)) return true;
|
|
37215
|
+
return false;
|
|
37216
|
+
};
|
|
37217
|
+
const classifyMotionExport = (exportName) => ({
|
|
37218
|
+
isAnimationFunction: MOTION_ANIMATION_FUNCTION_EXPORT_NAMES.has(exportName),
|
|
37219
|
+
isMotionComponent: false,
|
|
37220
|
+
isMotionComponentFactory: MOTION_COMPONENT_FACTORY_EXPORT_NAMES.has(exportName),
|
|
37221
|
+
isMotionComponentNamespace: MOTION_COMPONENT_NAMESPACE_EXPORT_NAMES.has(exportName),
|
|
37222
|
+
isMotionConfig: exportName === MOTION_CONFIG_EXPORT_NAME,
|
|
37223
|
+
isMotionNamespace: false,
|
|
37224
|
+
isReducedMotionHook: exportName === REDUCED_MOTION_HOOK_EXPORT_NAME
|
|
37225
|
+
});
|
|
37226
|
+
const getImportModuleSource = (node) => {
|
|
37227
|
+
let currentNode = node;
|
|
37228
|
+
while (currentNode) {
|
|
37229
|
+
if (ts.isImportDeclaration(currentNode) && ts.isStringLiteral(currentNode.moduleSpecifier)) return currentNode.moduleSpecifier.text;
|
|
37230
|
+
currentNode = currentNode.parent;
|
|
37231
|
+
}
|
|
37232
|
+
return null;
|
|
37233
|
+
};
|
|
37234
|
+
const getImportedBindingEvidence = (declaration, typeChecker, program, visitedSymbols) => {
|
|
37235
|
+
const moduleSource = getImportModuleSource(declaration);
|
|
37236
|
+
if (!moduleSource) return null;
|
|
37237
|
+
if (isMotionModuleSource(moduleSource) && ts.isNamespaceImport(declaration)) return {
|
|
37238
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37239
|
+
isMotionNamespace: true
|
|
37240
|
+
};
|
|
37241
|
+
if (isMotionModuleSource(moduleSource) && ts.isImportSpecifier(declaration)) {
|
|
37242
|
+
if (declaration.isTypeOnly) return null;
|
|
37243
|
+
return classifyMotionExport(declaration.propertyName?.text ?? declaration.name.text);
|
|
37244
|
+
}
|
|
37245
|
+
if (isMotionModuleSource(moduleSource) && ts.isImportClause(declaration)) {
|
|
37246
|
+
if (declaration.isTypeOnly) return null;
|
|
37247
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37248
|
+
}
|
|
37249
|
+
if (ts.isImportSpecifier(declaration) && !declaration.isTypeOnly || ts.isImportClause(declaration) && !declaration.isTypeOnly && declaration.name) {
|
|
37250
|
+
const importedName = ts.isImportSpecifier(declaration) ? declaration.propertyName?.text ?? declaration.name.text : "default";
|
|
37251
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, declaration.getSourceFile().fileName, program);
|
|
37252
|
+
if (!moduleSourceFile) return null;
|
|
37253
|
+
return resolveModuleExportEvidence(moduleSourceFile, importedName, typeChecker, program, visitedSymbols);
|
|
37254
|
+
}
|
|
37255
|
+
return null;
|
|
37256
|
+
};
|
|
37257
|
+
const getLocalModuleSourceFile = (moduleSource, importingFileName, program) => {
|
|
37258
|
+
if (!moduleSource.startsWith(".")) return null;
|
|
37259
|
+
const moduleBasePath = Path.resolve(Path.dirname(importingFileName), moduleSource);
|
|
37260
|
+
const moduleBaseExtension = Path.extname(moduleBasePath);
|
|
37261
|
+
const typescriptModuleBasePath = moduleBaseExtension === ".js" || moduleBaseExtension === ".jsx" ? moduleBasePath.slice(0, -moduleBaseExtension.length) : null;
|
|
37262
|
+
const candidates = [
|
|
37263
|
+
moduleBasePath,
|
|
37264
|
+
...typescriptModuleBasePath ? [
|
|
37265
|
+
`${typescriptModuleBasePath}.ts`,
|
|
37266
|
+
`${typescriptModuleBasePath}.tsx`,
|
|
37267
|
+
Path.join(typescriptModuleBasePath, "index.ts"),
|
|
37268
|
+
Path.join(typescriptModuleBasePath, "index.tsx")
|
|
37269
|
+
] : [],
|
|
37270
|
+
...SCRIPT_MODULE_EXTENSIONS.map((extension) => `${moduleBasePath}${extension}`),
|
|
37271
|
+
...SCRIPT_MODULE_EXTENSIONS.map((extension) => Path.join(moduleBasePath, `index${extension}`))
|
|
37272
|
+
];
|
|
37273
|
+
for (const candidate of candidates) {
|
|
37274
|
+
const sourceFile = program.getSourceFile(candidate);
|
|
37275
|
+
if (sourceFile) return sourceFile;
|
|
37276
|
+
}
|
|
37277
|
+
return null;
|
|
37278
|
+
};
|
|
37279
|
+
const resolveModuleExportEvidence = (sourceFile, exportName, typeChecker, program, visitedSymbols) => {
|
|
37280
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
37281
|
+
if (moduleSymbol && visitedSymbols.has(moduleSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37282
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37283
|
+
if (moduleSymbol) nextVisitedSymbols.add(moduleSymbol);
|
|
37284
|
+
for (const statement of sourceFile.statements) {
|
|
37285
|
+
if (exportName === "default" && ts.isExportAssignment(statement) && !statement.isExportEquals) {
|
|
37286
|
+
const evidence = resolveMotionExpressionEvidence(statement.expression, typeChecker, program, nextVisitedSymbols);
|
|
37287
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37288
|
+
continue;
|
|
37289
|
+
}
|
|
37290
|
+
if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) continue;
|
|
37291
|
+
if (statement.isTypeOnly) continue;
|
|
37292
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier)) continue;
|
|
37293
|
+
const moduleSource = statement.moduleSpecifier.text;
|
|
37294
|
+
if (!statement.exportClause) {
|
|
37295
|
+
if (isMotionModuleSource(moduleSource)) {
|
|
37296
|
+
const evidence = classifyMotionExport(exportName);
|
|
37297
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37298
|
+
continue;
|
|
37299
|
+
}
|
|
37300
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
37301
|
+
if (moduleSourceFile) {
|
|
37302
|
+
const evidence = resolveModuleExportEvidence(moduleSourceFile, exportName, typeChecker, program, nextVisitedSymbols);
|
|
37303
|
+
if (hasMotionExpressionEvidence(evidence)) return evidence;
|
|
37304
|
+
}
|
|
37305
|
+
continue;
|
|
37306
|
+
}
|
|
37307
|
+
if (!ts.isNamedExports(statement.exportClause)) continue;
|
|
37308
|
+
for (const exportSpecifier of statement.exportClause.elements) {
|
|
37309
|
+
if (exportSpecifier.name.text !== exportName || exportSpecifier.isTypeOnly) continue;
|
|
37310
|
+
const sourceExportName = exportSpecifier.propertyName?.text ?? exportSpecifier.name.text;
|
|
37311
|
+
if (isMotionModuleSource(moduleSource)) return classifyMotionExport(sourceExportName);
|
|
37312
|
+
const moduleSourceFile = getLocalModuleSourceFile(moduleSource, sourceFile.fileName, program);
|
|
37313
|
+
if (!moduleSourceFile) continue;
|
|
37314
|
+
return resolveModuleExportEvidence(moduleSourceFile, sourceExportName, typeChecker, program, nextVisitedSymbols);
|
|
37315
|
+
}
|
|
37316
|
+
}
|
|
37317
|
+
if (!moduleSymbol) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37318
|
+
const exportedSymbol = typeChecker.getExportsOfModule(moduleSymbol).find((candidateSymbol) => candidateSymbol.name === exportName);
|
|
37319
|
+
if (!exportedSymbol || nextVisitedSymbols.has(exportedSymbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37320
|
+
nextVisitedSymbols.add(exportedSymbol);
|
|
37321
|
+
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37322
|
+
for (const declaration of exportedSymbol.declarations ?? []) {
|
|
37323
|
+
if (ts.isExportSpecifier(declaration)) {
|
|
37324
|
+
const targetSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(declaration);
|
|
37325
|
+
for (const targetDeclaration of targetSymbol?.declarations ?? []) {
|
|
37326
|
+
const importedEvidence = getImportedBindingEvidence(targetDeclaration, typeChecker, program, nextVisitedSymbols);
|
|
37327
|
+
if (importedEvidence) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
37328
|
+
if (ts.isVariableDeclaration(targetDeclaration) && targetDeclaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(targetDeclaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37329
|
+
}
|
|
37330
|
+
}
|
|
37331
|
+
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37332
|
+
}
|
|
37333
|
+
return resolvedEvidence;
|
|
37334
|
+
};
|
|
37335
|
+
const mergeMotionExpressionEvidence = (leftEvidence, rightEvidence) => ({
|
|
37336
|
+
isAnimationFunction: leftEvidence.isAnimationFunction || rightEvidence.isAnimationFunction,
|
|
37337
|
+
isMotionComponent: leftEvidence.isMotionComponent || rightEvidence.isMotionComponent,
|
|
37338
|
+
isMotionComponentFactory: leftEvidence.isMotionComponentFactory || rightEvidence.isMotionComponentFactory,
|
|
37339
|
+
isMotionComponentNamespace: leftEvidence.isMotionComponentNamespace || rightEvidence.isMotionComponentNamespace,
|
|
37340
|
+
isMotionConfig: leftEvidence.isMotionConfig || rightEvidence.isMotionConfig,
|
|
37341
|
+
isMotionNamespace: leftEvidence.isMotionNamespace || rightEvidence.isMotionNamespace,
|
|
37342
|
+
isReducedMotionHook: leftEvidence.isReducedMotionHook || rightEvidence.isReducedMotionHook
|
|
37343
|
+
});
|
|
37344
|
+
const hasMotionExpressionEvidence = (evidence) => evidence.isAnimationFunction || evidence.isMotionComponent || evidence.isMotionComponentFactory || evidence.isMotionComponentNamespace || evidence.isMotionConfig || evidence.isMotionNamespace || evidence.isReducedMotionHook;
|
|
37345
|
+
const classifyMotionMember = (receiverEvidence, memberName) => {
|
|
37346
|
+
if (receiverEvidence.isMotionNamespace) return classifyMotionExport(memberName);
|
|
37347
|
+
if (receiverEvidence.isMotionComponentFactory) return {
|
|
37348
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37349
|
+
isMotionComponent: true
|
|
37350
|
+
};
|
|
37351
|
+
if (receiverEvidence.isMotionComponentNamespace && MOTION_COMPONENT_NAMESPACE_MEMBER_NAMES.has(memberName)) return {
|
|
37352
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37353
|
+
isMotionComponent: true
|
|
37354
|
+
};
|
|
37355
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37356
|
+
};
|
|
37357
|
+
const resolveMotionExpressionEvidence = (expression, typeChecker, program, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
37358
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
37359
|
+
if (ts.isIdentifier(unwrappedExpression)) {
|
|
37360
|
+
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
37361
|
+
if (!symbol || visitedSymbols.has(symbol)) return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37362
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37363
|
+
nextVisitedSymbols.add(symbol);
|
|
37364
|
+
let resolvedEvidence = EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37365
|
+
for (const declaration of symbol.declarations ?? []) {
|
|
37366
|
+
const importedEvidence = getImportedBindingEvidence(declaration, typeChecker, program, nextVisitedSymbols);
|
|
37367
|
+
if (importedEvidence) {
|
|
37368
|
+
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, importedEvidence);
|
|
37369
|
+
continue;
|
|
37370
|
+
}
|
|
37371
|
+
if (ts.isVariableDeclaration(declaration) && declaration.initializer) resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, resolveMotionExpressionEvidence(declaration.initializer, typeChecker, program, nextVisitedSymbols));
|
|
37372
|
+
if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent) && ts.isVariableDeclaration(declaration.parent.parent) && declaration.parent.parent.initializer) {
|
|
37373
|
+
const propertyName = declaration.propertyName ?? declaration.name;
|
|
37374
|
+
if (ts.isIdentifier(propertyName) || ts.isStringLiteral(propertyName)) {
|
|
37375
|
+
const receiverEvidence = resolveMotionExpressionEvidence(declaration.parent.parent.initializer, typeChecker, program, nextVisitedSymbols);
|
|
37376
|
+
resolvedEvidence = mergeMotionExpressionEvidence(resolvedEvidence, classifyMotionMember(receiverEvidence, propertyName.text));
|
|
37377
|
+
}
|
|
37378
|
+
}
|
|
37379
|
+
}
|
|
37380
|
+
return resolvedEvidence;
|
|
37381
|
+
}
|
|
37382
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression)) return classifyMotionMember(resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols), unwrappedExpression.name.text);
|
|
37383
|
+
if (ts.isElementAccessExpression(unwrappedExpression) && unwrappedExpression.argumentExpression && (ts.isStringLiteral(unwrappedExpression.argumentExpression) || ts.isNoSubstitutionTemplateLiteral(unwrappedExpression.argumentExpression))) return classifyMotionMember(resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols), unwrappedExpression.argumentExpression.text);
|
|
37384
|
+
if (ts.isCallExpression(unwrappedExpression)) {
|
|
37385
|
+
if (ts.isIdentifier(unwrappedExpression.expression) && unwrappedExpression.expression.text === "require" && !typeChecker.getSymbolAtLocation(unwrappedExpression.expression) && unwrappedExpression.arguments.length === 1 && ts.isStringLiteral(unwrappedExpression.arguments[0]) && isMotionModuleSource(unwrappedExpression.arguments[0].text)) return {
|
|
37386
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37387
|
+
isMotionNamespace: true
|
|
37388
|
+
};
|
|
37389
|
+
if (ts.isPropertyAccessExpression(unwrappedExpression.expression) && unwrappedExpression.expression.name.text === "bind") {
|
|
37390
|
+
const boundReceiverEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression.expression, typeChecker, program, visitedSymbols);
|
|
37391
|
+
if (boundReceiverEvidence.isAnimationFunction) return boundReceiverEvidence;
|
|
37392
|
+
}
|
|
37393
|
+
const calleeEvidence = resolveMotionExpressionEvidence(unwrappedExpression.expression, typeChecker, program, visitedSymbols);
|
|
37394
|
+
if (calleeEvidence.isMotionComponentFactory) return {
|
|
37395
|
+
...EMPTY_MOTION_EXPRESSION_EVIDENCE,
|
|
37396
|
+
isMotionComponent: true
|
|
37397
|
+
};
|
|
37398
|
+
return calleeEvidence;
|
|
37399
|
+
}
|
|
37400
|
+
return EMPTY_MOTION_EXPRESSION_EVIDENCE;
|
|
37401
|
+
};
|
|
37402
|
+
const getStaticStringExpressionValue = (expression, typeChecker, visitedSymbols = /* @__PURE__ */ new Set()) => {
|
|
37403
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
37404
|
+
if (ts.isStringLiteral(unwrappedExpression) || ts.isNoSubstitutionTemplateLiteral(unwrappedExpression)) return unwrappedExpression.text;
|
|
37405
|
+
if (!ts.isIdentifier(unwrappedExpression)) return null;
|
|
37406
|
+
const symbol = typeChecker.getSymbolAtLocation(unwrappedExpression);
|
|
37407
|
+
if (!symbol || visitedSymbols.has(symbol)) return null;
|
|
37408
|
+
const nextVisitedSymbols = new Set(visitedSymbols);
|
|
37409
|
+
nextVisitedSymbols.add(symbol);
|
|
37410
|
+
for (const declaration of symbol.declarations ?? []) {
|
|
37411
|
+
if (!ts.isVariableDeclaration(declaration) || !declaration.initializer) continue;
|
|
37412
|
+
if (!ts.isVariableDeclarationList(declaration.parent)) continue;
|
|
37413
|
+
if (!(declaration.parent.flags & ts.NodeFlags.Const)) continue;
|
|
37414
|
+
const value = getStaticStringExpressionValue(declaration.initializer, typeChecker, nextVisitedSymbols);
|
|
37415
|
+
if (value !== null) return value;
|
|
37416
|
+
}
|
|
37417
|
+
return null;
|
|
37418
|
+
};
|
|
37419
|
+
const getStaticJsxAttributeValue = (attribute, typeChecker) => {
|
|
37420
|
+
if (!attribute.initializer) return null;
|
|
37421
|
+
if (ts.isStringLiteral(attribute.initializer)) return attribute.initializer.text;
|
|
37422
|
+
if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression) return null;
|
|
37423
|
+
return getStaticStringExpressionValue(attribute.initializer.expression, typeChecker);
|
|
37424
|
+
};
|
|
37425
|
+
const isExpressionValueConsumed = (expression) => {
|
|
37426
|
+
let currentExpression = expression;
|
|
37427
|
+
while (ts.isParenthesizedExpression(currentExpression.parent) || ts.isAsExpression(currentExpression.parent) || ts.isSatisfiesExpression(currentExpression.parent) || ts.isNonNullExpression(currentExpression.parent) || ts.isTypeAssertionExpression(currentExpression.parent)) currentExpression = currentExpression.parent;
|
|
37428
|
+
return !ts.isExpressionStatement(currentExpression.parent) && !ts.isVoidExpression(currentExpression.parent);
|
|
37429
|
+
};
|
|
37430
|
+
const jsxElementHasReducedMotionConfiguration = (attributes, typeChecker) => attributes.properties.some((attribute) => ts.isJsxAttribute(attribute) && ts.isIdentifier(attribute.name) && attribute.name.text === REDUCED_MOTION_PROP_NAME && REDUCED_MOTION_CONFIG_VALUES.has(getStaticJsxAttributeValue(attribute, typeChecker) ?? ""));
|
|
37431
|
+
const collectScriptMotionEvidence = (sourceFile, typeChecker, program) => {
|
|
37432
|
+
const evidence = {
|
|
37433
|
+
hasMotionUse: false,
|
|
37434
|
+
hasReducedMotionHandling: false
|
|
37435
|
+
};
|
|
37436
|
+
const visitNode = (node) => {
|
|
37437
|
+
if (ts.isCallExpression(node)) {
|
|
37438
|
+
const calleeEvidence = resolveMotionExpressionEvidence(node.expression, typeChecker, program);
|
|
37439
|
+
const isAnimationFunctionCallViaCallOrApply = (ts.isPropertyAccessExpression(node.expression) && (node.expression.name.text === "call" || node.expression.name.text === "apply") || ts.isElementAccessExpression(node.expression) && node.expression.argumentExpression && (ts.isStringLiteral(node.expression.argumentExpression) || ts.isNoSubstitutionTemplateLiteral(node.expression.argumentExpression)) && (node.expression.argumentExpression.text === "call" || node.expression.argumentExpression.text === "apply")) && resolveMotionExpressionEvidence(node.expression.expression, typeChecker, program).isAnimationFunction;
|
|
37440
|
+
if (calleeEvidence.isAnimationFunction || isAnimationFunctionCallViaCallOrApply) evidence.hasMotionUse = true;
|
|
37441
|
+
if (calleeEvidence.isReducedMotionHook && isExpressionValueConsumed(node)) evidence.hasReducedMotionHandling = true;
|
|
37442
|
+
}
|
|
37443
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
37444
|
+
const tagEvidence = ts.isJsxNamespacedName(node.tagName) ? EMPTY_MOTION_EXPRESSION_EVIDENCE : resolveMotionExpressionEvidence(node.tagName, typeChecker, program);
|
|
37445
|
+
if (tagEvidence.isMotionComponent || tagEvidence.isMotionComponentFactory) evidence.hasMotionUse = true;
|
|
37446
|
+
if (tagEvidence.isMotionConfig && jsxElementHasReducedMotionConfiguration(node.attributes, typeChecker)) evidence.hasReducedMotionHandling = true;
|
|
37447
|
+
}
|
|
37448
|
+
ts.forEachChild(node, visitNode);
|
|
37449
|
+
};
|
|
37450
|
+
visitNode(sourceFile);
|
|
37451
|
+
return evidence;
|
|
37452
|
+
};
|
|
37453
|
+
const analyzeReducedMotionSources = (sources) => {
|
|
37454
|
+
if (!sources.some(({ sourceText }) => MOTION_SOURCE_PREFILTER.test(sourceText))) return {
|
|
37455
|
+
hasMotionUse: false,
|
|
37456
|
+
hasReducedMotionHandling: false
|
|
37457
|
+
};
|
|
37458
|
+
const compilerOptions = {
|
|
37459
|
+
allowJs: true,
|
|
37460
|
+
checkJs: false,
|
|
37461
|
+
jsx: ts.JsxEmit.Preserve,
|
|
37462
|
+
module: ts.ModuleKind.ESNext,
|
|
37463
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
37464
|
+
noEmit: true,
|
|
37465
|
+
noLib: true,
|
|
37466
|
+
noResolve: true,
|
|
37467
|
+
skipLibCheck: true,
|
|
37468
|
+
target: ts.ScriptTarget.Latest
|
|
37469
|
+
};
|
|
37470
|
+
const sourceTextByFileName = new Map(sources.map(({ fileName: sourceFileName, sourceText: content }) => [Path.resolve(sourceFileName), content]));
|
|
37471
|
+
const compilerHost = ts.createCompilerHost(compilerOptions);
|
|
37472
|
+
const getDefaultSourceFile = compilerHost.getSourceFile.bind(compilerHost);
|
|
37473
|
+
compilerHost.getSourceFile = (requestedFileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => sourceTextByFileName.has(Path.resolve(requestedFileName)) ? ts.createSourceFile(Path.resolve(requestedFileName), sourceTextByFileName.get(Path.resolve(requestedFileName)) ?? "", languageVersionOrOptions, true, getTypescriptScriptKind(requestedFileName)) : getDefaultSourceFile(requestedFileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
37474
|
+
const program = ts.createProgram([...sourceTextByFileName.keys()], compilerOptions, compilerHost);
|
|
37475
|
+
const typeChecker = program.getTypeChecker();
|
|
37476
|
+
const evidence = {
|
|
37477
|
+
hasMotionUse: false,
|
|
37478
|
+
hasReducedMotionHandling: false
|
|
37479
|
+
};
|
|
37480
|
+
for (const sourceFileName of sourceTextByFileName.keys()) {
|
|
37481
|
+
const sourceFile = program.getSourceFile(sourceFileName);
|
|
37482
|
+
if (!sourceFile) continue;
|
|
37483
|
+
const fileEvidence = collectScriptMotionEvidence(sourceFile, typeChecker, program);
|
|
37484
|
+
evidence.hasMotionUse ||= fileEvidence.hasMotionUse;
|
|
37485
|
+
evidence.hasReducedMotionHandling ||= fileEvidence.hasReducedMotionHandling;
|
|
37486
|
+
}
|
|
37487
|
+
return evidence;
|
|
37488
|
+
};
|
|
37489
|
+
const removeCssCommentsAndStrings = (content) => {
|
|
37490
|
+
let sanitizedContent = "";
|
|
37491
|
+
let quote = null;
|
|
37492
|
+
let isInsideComment = false;
|
|
37493
|
+
let isInsideLineComment = false;
|
|
37494
|
+
for (let characterIndex = 0; characterIndex < content.length; characterIndex += 1) {
|
|
37495
|
+
const character = content[characterIndex];
|
|
37496
|
+
const nextCharacter = content[characterIndex + 1];
|
|
37497
|
+
if (isInsideLineComment) {
|
|
37498
|
+
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37499
|
+
if (character === "\n") isInsideLineComment = false;
|
|
37500
|
+
continue;
|
|
37501
|
+
}
|
|
37502
|
+
if (isInsideComment) {
|
|
37503
|
+
if (character === "*" && nextCharacter === "/") {
|
|
37504
|
+
sanitizedContent += " ";
|
|
37505
|
+
characterIndex += 1;
|
|
37506
|
+
isInsideComment = false;
|
|
37507
|
+
} else sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37508
|
+
continue;
|
|
37509
|
+
}
|
|
37510
|
+
if (quote) {
|
|
37511
|
+
if (character === "\\") {
|
|
37512
|
+
sanitizedContent += " ";
|
|
37513
|
+
characterIndex += 1;
|
|
37514
|
+
continue;
|
|
37515
|
+
}
|
|
37516
|
+
if (character === quote) quote = null;
|
|
37517
|
+
sanitizedContent += character === "\n" ? "\n" : " ";
|
|
37518
|
+
continue;
|
|
37519
|
+
}
|
|
37520
|
+
if (character === "/" && nextCharacter === "*") {
|
|
37521
|
+
sanitizedContent += " ";
|
|
37522
|
+
characterIndex += 1;
|
|
37523
|
+
isInsideComment = true;
|
|
37524
|
+
continue;
|
|
37525
|
+
}
|
|
37526
|
+
if (character === "/" && nextCharacter === "/") {
|
|
37527
|
+
sanitizedContent += " ";
|
|
37528
|
+
characterIndex += 1;
|
|
37529
|
+
isInsideLineComment = true;
|
|
37530
|
+
continue;
|
|
37531
|
+
}
|
|
37532
|
+
if (character === "\"" || character === "'") {
|
|
37533
|
+
sanitizedContent += " ";
|
|
37534
|
+
quote = character;
|
|
37535
|
+
continue;
|
|
37536
|
+
}
|
|
37537
|
+
sanitizedContent += character;
|
|
37538
|
+
}
|
|
37539
|
+
return sanitizedContent;
|
|
37540
|
+
};
|
|
37541
|
+
const findMatchingClosingBrace = (content, openingBraceIndex) => {
|
|
37542
|
+
let depth = 0;
|
|
37543
|
+
for (let characterIndex = openingBraceIndex; characterIndex < content.length; characterIndex += 1) {
|
|
37544
|
+
if (content[characterIndex] === "{") depth += 1;
|
|
37545
|
+
if (content[characterIndex] !== "}") continue;
|
|
37546
|
+
depth -= 1;
|
|
37547
|
+
if (depth === 0) return characterIndex;
|
|
37548
|
+
}
|
|
37549
|
+
return -1;
|
|
37550
|
+
};
|
|
37551
|
+
const hasReducedMotionMediaQuery = (content) => {
|
|
37552
|
+
const sanitizedContent = removeCssCommentsAndStrings(content);
|
|
37553
|
+
REDUCED_MOTION_MEDIA_QUERY_PATTERN.lastIndex = 0;
|
|
37554
|
+
for (const match of sanitizedContent.matchAll(REDUCED_MOTION_MEDIA_QUERY_PATTERN)) {
|
|
37555
|
+
const mediaPrelude = match[1];
|
|
37556
|
+
if (/\bnot\b/i.test(mediaPrelude)) continue;
|
|
37557
|
+
const openingBraceIndex = (match.index ?? 0) + match[0].lastIndexOf("{");
|
|
37558
|
+
const closingBraceIndex = findMatchingClosingBrace(sanitizedContent, openingBraceIndex);
|
|
37559
|
+
if (closingBraceIndex === -1) continue;
|
|
37560
|
+
const body = sanitizedContent.slice(openingBraceIndex + 1, closingBraceIndex);
|
|
37561
|
+
if (CSS_DECLARATION_PATTERN.test(body)) return true;
|
|
37562
|
+
}
|
|
37563
|
+
return false;
|
|
37564
|
+
};
|
|
37565
|
+
const collectProjectMotionEvidence = (rootDirectory) => {
|
|
37566
|
+
const scriptSources = [];
|
|
37567
|
+
let hasReducedMotionHandling = false;
|
|
37187
37568
|
for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
|
|
37188
|
-
|
|
37569
|
+
const extension = Path.extname(name);
|
|
37570
|
+
if (!SCRIPT_FILE_EXTENSIONS.has(extension) && !STYLE_FILE_EXTENSIONS.has(extension)) continue;
|
|
37189
37571
|
let content;
|
|
37190
37572
|
try {
|
|
37191
37573
|
content = NFS.readFileSync(absolutePath, "utf-8");
|
|
37192
37574
|
} catch {
|
|
37193
37575
|
continue;
|
|
37194
37576
|
}
|
|
37195
|
-
if (
|
|
37577
|
+
if (STYLE_FILE_EXTENSIONS.has(extension)) {
|
|
37578
|
+
if (hasReducedMotionMediaQuery(content)) hasReducedMotionHandling = true;
|
|
37579
|
+
continue;
|
|
37580
|
+
}
|
|
37581
|
+
scriptSources.push({
|
|
37582
|
+
fileName: absolutePath,
|
|
37583
|
+
sourceText: content
|
|
37584
|
+
});
|
|
37196
37585
|
}
|
|
37197
|
-
return
|
|
37586
|
+
if (scriptSources.length === 0) return {
|
|
37587
|
+
hasMotionUse: false,
|
|
37588
|
+
hasReducedMotionHandling
|
|
37589
|
+
};
|
|
37590
|
+
const scriptEvidence = analyzeReducedMotionSources(scriptSources);
|
|
37591
|
+
const hasMotionUse = scriptEvidence.hasMotionUse;
|
|
37592
|
+
hasReducedMotionHandling ||= scriptEvidence.hasReducedMotionHandling;
|
|
37593
|
+
return {
|
|
37594
|
+
hasMotionUse,
|
|
37595
|
+
hasReducedMotionHandling
|
|
37596
|
+
};
|
|
37198
37597
|
};
|
|
37199
37598
|
const checkReducedMotion = (rootDirectory) => {
|
|
37200
37599
|
const packageJsonPath = Path.join(rootDirectory, "package.json");
|
|
37201
37600
|
if (!isFile(packageJsonPath)) return [];
|
|
37202
|
-
let hasMotionLibrary = false;
|
|
37203
37601
|
try {
|
|
37204
37602
|
const packageJson = readPackageJson(packageJsonPath);
|
|
37205
37603
|
const allDependencies = {
|
|
37206
37604
|
...packageJson.dependencies,
|
|
37207
37605
|
...packageJson.devDependencies
|
|
37208
37606
|
};
|
|
37209
|
-
|
|
37607
|
+
if (!Object.keys(allDependencies).some((packageName) => MOTION_LIBRARY_PACKAGES.has(packageName))) return [];
|
|
37210
37608
|
} catch {
|
|
37211
37609
|
return [];
|
|
37212
37610
|
}
|
|
37213
|
-
|
|
37214
|
-
|
|
37215
|
-
"grep",
|
|
37216
|
-
"--untracked",
|
|
37217
|
-
"-lE",
|
|
37218
|
-
REDUCED_MOTION_GREP_PATTERN,
|
|
37219
|
-
"--",
|
|
37220
|
-
...REDUCED_MOTION_FILE_GLOBS
|
|
37221
|
-
], {
|
|
37222
|
-
cwd: rootDirectory,
|
|
37223
|
-
encoding: "utf-8",
|
|
37224
|
-
stdio: [
|
|
37225
|
-
"ignore",
|
|
37226
|
-
"pipe",
|
|
37227
|
-
"pipe"
|
|
37228
|
-
]
|
|
37229
|
-
});
|
|
37230
|
-
if (!(!result.error && (result.status === 0 || result.status === GIT_GREP_NO_MATCH_STATUS))) return hasReducedMotionHandlingViaFilesystem(rootDirectory) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
37231
|
-
return result.status === 0 && result.stdout.split("\n").some((filePath) => filePath.length > 0 && !hasIgnoredPathSegment(filePath)) ? [] : [MISSING_REDUCED_MOTION_DIAGNOSTIC];
|
|
37611
|
+
const evidence = collectProjectMotionEvidence(rootDirectory);
|
|
37612
|
+
return evidence.hasMotionUse && !evidence.hasReducedMotionHandling ? [MISSING_REDUCED_MOTION_DIAGNOSTIC] : [];
|
|
37232
37613
|
};
|
|
37233
37614
|
const buildSecurityScanDiagnostic = (finding, entry, relativePath) => ({
|
|
37234
37615
|
filePath: relativePath,
|
|
@@ -39831,23 +40212,12 @@ const REACT_USE_BINDING_RESOLUTION = {
|
|
|
39831
40212
|
isReactUseBinding: true,
|
|
39832
40213
|
isReactNamespaceBinding: false
|
|
39833
40214
|
};
|
|
39834
|
-
const getScriptKind$2 = (filename) => {
|
|
39835
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
39836
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
39837
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
39838
|
-
return ts.ScriptKind.JS;
|
|
39839
|
-
};
|
|
39840
40215
|
const getUtf16Offset$1 = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
39841
|
-
const unwrapExpression = (expression) => {
|
|
39842
|
-
let currentExpression = expression;
|
|
39843
|
-
while (ts.isParenthesizedExpression(currentExpression) || ts.isAsExpression(currentExpression) || ts.isSatisfiesExpression(currentExpression) || ts.isNonNullExpression(currentExpression) || ts.isTypeAssertionExpression(currentExpression)) currentExpression = currentExpression.expression;
|
|
39844
|
-
return currentExpression;
|
|
39845
|
-
};
|
|
39846
40216
|
const getStaticPropertyName = (node) => {
|
|
39847
40217
|
if (!node) return null;
|
|
39848
40218
|
if (ts.isIdentifier(node) || ts.isStringLiteral(node) || ts.isNumericLiteral(node)) return node.text;
|
|
39849
40219
|
if (ts.isComputedPropertyName(node)) {
|
|
39850
|
-
const expression =
|
|
40220
|
+
const expression = unwrapTypescriptExpression(node.expression);
|
|
39851
40221
|
if (ts.isStringLiteral(expression) || ts.isNoSubstitutionTemplateLiteral(expression)) return expression.text;
|
|
39852
40222
|
}
|
|
39853
40223
|
return null;
|
|
@@ -39876,7 +40246,7 @@ const isReactUseObjectBindingElement = (bindingElement) => {
|
|
|
39876
40246
|
return getStaticPropertyName(bindingElement.propertyName) === USE_IDENTIFIER;
|
|
39877
40247
|
};
|
|
39878
40248
|
const isReactRequireCall = (expression) => {
|
|
39879
|
-
const unwrappedExpression =
|
|
40249
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
39880
40250
|
return ts.isCallExpression(unwrappedExpression) && ts.isIdentifier(unwrappedExpression.expression) && unwrappedExpression.expression.text === REQUIRE_IDENTIFIER && unwrappedExpression.arguments.length === 1 && ts.isStringLiteral(unwrappedExpression.arguments[0]) && unwrappedExpression.arguments[0].text === REACT_MODULE_SOURCE;
|
|
39881
40251
|
};
|
|
39882
40252
|
const getModuleSource = (node) => {
|
|
@@ -39978,7 +40348,7 @@ const isIdentifierShadowedByLocalBinding = (identifier, sourceFile) => {
|
|
|
39978
40348
|
return false;
|
|
39979
40349
|
};
|
|
39980
40350
|
const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
39981
|
-
const unwrappedExpression =
|
|
40351
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
39982
40352
|
if (isReactRequireCall(unwrappedExpression)) return true;
|
|
39983
40353
|
if (!ts.isIdentifier(unwrappedExpression)) return false;
|
|
39984
40354
|
if (reactImportBindings.namespaceNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
@@ -39986,7 +40356,7 @@ const isReactNamespaceExpression = (expression, reactImportBindings, sourceFile,
|
|
|
39986
40356
|
};
|
|
39987
40357
|
const isReactUseExpression = (expression, reactImportBindings, sourceFile, visitedDeclarations) => {
|
|
39988
40358
|
if (!expression) return false;
|
|
39989
|
-
const unwrappedExpression =
|
|
40359
|
+
const unwrappedExpression = unwrapTypescriptExpression(expression);
|
|
39990
40360
|
if (ts.isIdentifier(unwrappedExpression)) {
|
|
39991
40361
|
if (reactImportBindings.useImportNames.has(unwrappedExpression.text) && !isIdentifierShadowedByLocalBinding(unwrappedExpression, sourceFile)) return true;
|
|
39992
40362
|
if (unwrappedExpression.text === USE_IDENTIFIER) return false;
|
|
@@ -40086,7 +40456,7 @@ const findUseCallIdentifier = (sourceFile, useOffset) => {
|
|
|
40086
40456
|
return matchedIdentifier;
|
|
40087
40457
|
};
|
|
40088
40458
|
const resolveUseCallBinding = (sourceText, filename, utf8Offset) => {
|
|
40089
|
-
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true,
|
|
40459
|
+
const sourceFile = ts.createSourceFile(filename, sourceText, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(filename));
|
|
40090
40460
|
const useIdentifier = findUseCallIdentifier(sourceFile, getUtf16Offset$1(sourceText, utf8Offset));
|
|
40091
40461
|
if (!useIdentifier) return null;
|
|
40092
40462
|
return resolveIdentifierBinding(useIdentifier, collectReactImportBindings(sourceFile), sourceFile);
|
|
@@ -40122,12 +40492,6 @@ const WORKLET_ACCEPTING_CALLEES = new Set([
|
|
|
40122
40492
|
"executeOnUIRuntimeSync"
|
|
40123
40493
|
]);
|
|
40124
40494
|
const GESTURE_ROOT_IDENTIFIER = "Gesture";
|
|
40125
|
-
const getScriptKind$1 = (filename) => {
|
|
40126
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
40127
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
40128
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
40129
|
-
return ts.ScriptKind.JS;
|
|
40130
|
-
};
|
|
40131
40495
|
const getUtf16Offset = (sourceText, utf8Offset) => Buffer.from(sourceText).subarray(0, utf8Offset).toString("utf8").length;
|
|
40132
40496
|
const hasWorkletDirective = (node) => {
|
|
40133
40497
|
if (!ts.isFunctionDeclaration(node) && !ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isMethodDeclaration(node)) return false;
|
|
@@ -40199,17 +40563,11 @@ const shouldSuppressCompilerFindingInWorklet = (diagnostic, project, rootDirecto
|
|
|
40199
40563
|
} catch {
|
|
40200
40564
|
return false;
|
|
40201
40565
|
}
|
|
40202
|
-
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true,
|
|
40566
|
+
return isOffsetInsideWorklet(ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true, getTypescriptScriptKind(absolutePath)), getUtf16Offset(sourceText, primaryLabel.span.offset));
|
|
40203
40567
|
};
|
|
40204
40568
|
const MANUAL_MEMOIZATION_PLUGIN = "react-doctor";
|
|
40205
40569
|
const MANUAL_MEMOIZATION_RULE = "react-compiler-no-manual-memoization";
|
|
40206
40570
|
const REACT_COMPILER_PLUGIN = "react-hooks-js";
|
|
40207
|
-
const getScriptKind = (filename) => {
|
|
40208
|
-
if (filename.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
40209
|
-
if (filename.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
40210
|
-
if (filename.endsWith(".ts")) return ts.ScriptKind.TS;
|
|
40211
|
-
return ts.ScriptKind.JS;
|
|
40212
|
-
};
|
|
40213
40571
|
const isManualMemoizationDiagnostic = (diagnostic) => diagnostic.plugin === MANUAL_MEMOIZATION_PLUGIN && diagnostic.rule === MANUAL_MEMOIZATION_RULE;
|
|
40214
40572
|
const nodeLineRange = (sourceFile, node) => ({
|
|
40215
40573
|
startLine: sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1,
|
|
@@ -40271,7 +40629,7 @@ const suppressMemoizationInBailedOutFunctions = (diagnostics, rootDirectory) =>
|
|
|
40271
40629
|
try {
|
|
40272
40630
|
const buffer = NFS.readFileSync(absolutePath);
|
|
40273
40631
|
parsed = {
|
|
40274
|
-
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true,
|
|
40632
|
+
sourceFile: ts.createSourceFile(absolutePath, buffer.toString("utf8"), ts.ScriptTarget.Latest, true, getTypescriptScriptKind(absolutePath)),
|
|
40275
40633
|
buffer
|
|
40276
40634
|
};
|
|
40277
40635
|
} catch {
|
|
@@ -44915,5 +45273,5 @@ const startLanguageServer = () => {
|
|
|
44915
45273
|
};
|
|
44916
45274
|
//#endregion
|
|
44917
45275
|
export { startLanguageServer };
|
|
44918
|
-
!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]="
|
|
44919
|
-
//# debugId=
|
|
45276
|
+
!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]="9428cea1-cc36-547a-941f-20487b0140fc")}catch(e){}}();
|
|
45277
|
+
//# debugId=9428cea1-cc36-547a-941f-20487b0140fc
|