Sentry eslintPluginScraps 新规则开发指南:四种 Rule Archetype 模式与源码实现解析
Sentry eslintPluginScraps 新规则开发指南四种 Rule Archetype 模式与源码实现解析【免费下载链接】sentryDeveloper-first error tracking and performance monitoring项目地址: https://gitcode.com/GitHub_Trending/sen/sentry本文面向需要为 Sentry 前端设计系统新增 ESLint 规则尤其是 CSS-in-JS / Emotion 样式与 JSX 结构约束类规则的开发者系统讲解.agents/skills/lint-new/references/rule-archetypes.md中定义的四类规则原型的选型依据、AST 访问器组织方式、自动修复安全性边界并对照仓库中static/oxlint/eslintPluginScraps的实际实现给出可复用的代码骨架。读完本文你将能够根据规则意图快速确定应采用哪种 AST 方案并正确复用createStyleCollector、createImportTracker等共享工具写出测试完备、可注册、可自动修复的新规则。一、先读懂这份参考文档的定位Sentry 前端仓库拥有一套独立的 lint 插件工程eslintPluginScraps位于 static/oxlint/eslintPluginScraps其中集中了针对设计系统、样式 token 与 CSS-in-JS 用法的规则。由于这类规则的 AST 遍历逻辑高度相似仓库以技能包形式沉淀了开发规范lint-new/SKILL.md 描述新建规则的完整流程而 rule-archetypes.md 则是选型与模式速查——它把你想让规则做什么与应该采用哪种 AST 方案一一对应本文即以该文档为核心骨架展开。规则意图与原型Archetype的对应关系是全文的出发点可用下面的决策表快速定位规则意图Archetype关键模式示例规则重写 import 路径Import rewrite导入重写ImportDeclarationvisitor配合fixer.replaceText(node.source, ...)no-core-import校验某个 token/值用于哪些 CSS 属性Property validation属性校验createStyleCollectorProgram:exit延迟校验use-semantic-token限制特定 props 中允许出现的 JSX 元素JSX structural constraintJSX 结构约束import 追踪 递归 JSX 树遍历 options schemarestrict-jsx-slot-children在静态 CSS 文本中检测模式选择器、原始值Template text analysis模板文本分析TaggedTemplateExpression→ 遍历quasi.quasis静态文本no-dom-couplingPR #109906下面逐一展开四个原型并结合eslintPluginScraps/src的真实源码佐证。二、Archetype 1Import Rewrite导入重写适用场景规则需要检查 import 的来源并重写它——例如禁止从某个内部模块导入、统一改写为新的包路径。核心模式只写一个ImportDeclarationvisitor自动修复autofix就是替换 source 字符串无需其它 AST 操作create(context) { return { ImportDeclaration(node) { const importPath node.source.value; if (typeof importPath string importPath.startsWith(FORBIDDEN)) { context.report({ node, messageId: ..., fix(fixer) { return fixer.replaceText(node.source, ${newPath}); }, }); } }, }; }自动修复安全性几乎总是安全的——修复仅改变一个字符串字面量不触碰标识符、不改变作用域。边界情况type-only 导入import type {...}、混合具名导入、re-exportexport {...} from都由ImportDeclaration统一覆盖因为只替换 source 字符串无需特殊处理。注意判断node.source.value为字符串类型跳过动态导入等非字面量场景再执行.startsWith(FORBIDDEN)。仓库对应实现仓库中的noCoreImport规则见 src/rules/noCoreImport.ts即此模式的典范SKILL.md 也明确将其列为safe autofix patterns的 canonical 示例。三、Archetype 2Property ValidationStyle Collector 属性校验适用场景规则要校验某个动态值theme token、变量被用在了哪些 CSS 属性上典型如use-semantic-token——它强制theme.tokens.*只能搭配与其语义类别匹配的 CSS 属性。关键洞察——两阶段设计two-phase与导入重写在访问期间即刻报告不同此类规则必须先收集、后校验调用createStyleCollector(context)得到{collector, visitors}将visitors展开进规则的返回值在Program:exit中遍历collector.getAll()逐个校验每条StyleDeclaration校验结束后调用collector.clear()做清理。create(context) { if (!shouldAnalyze(context)) return {}; // Fast bailout const {collector, visitors} createStyleCollector(context); return { ...visitors, Program:exit() { for (const decl of collector.getAll()) { // decl.property.name — the CSS property (already normalized) // decl.values — array of {rawNode, tokenInfo: {tokenPath, node}} validateDeclaration(decl); } collector.clear(); }, }; }2.1 createStyleCollector 的底层实现在 src/ast/extractor/index.ts 中createStyleCollector会把三路提取器的访问器聚合在一起createStyledExtractorstyled 模板字面量见 extractor/styled.tscreateCssPropExtractorEmotion 的cssprop见 extractor/cssProp.tscreateStylePropExtractor原生styleprop见 extractor/styleProp.ts。三者共享同一个collector并通过mergeVisitors同类型节点处理器会被合并串联执行与createThemeTrackertracker/theme.ts负责追踪useTheme()及回调中的 theme 绑定组合最终返回{collector, visitors, themeTracker}。重要提醒collector 只处理模板字符串里的插值表达式${...}部分即动态传入 CSS 属性的值不会分析quasis 中的静态 CSS 文本。若要在静态文本本身如裸十六进制颜色、嵌套选择器中检测模式请改用 Archetype 4。2.2 配置驱动把类别映射放进行 config 目录如果校验规则按类别变化应把映射关系放在src/config/中而非写死在规则逻辑里。仓库中 src/config/tokenRules.ts 即此模式的样板新增类别时通常只需编辑配置文件、无需改动规则逻辑。use-semantic-tokensrc/rules/useSemanticToken.ts的运行流程可印证先shouldAnalyze(context)快速退出createStyleCollector收集后在validateDeclaration中对每条声明取decl.property.name已归一化跳过--开头的 CSS 自定义属性遍历decl.values凡带tokenInfo的值用findRuleForToken(tokenPath)查配置src/config/tokenRules.ts若 token 所属类别的allowedProperties不包含当前属性则报告invalidProperty或带建议的invalidPropertyWithSuggestion后者借助PROPERTY_TO_RULE反查该属性应使用哪个类别的 token。此外该规则还支持enabledCategories选项用于按需开启/关闭某些 token 类别对应 SKILL.md 中提到的复杂 schema 可参考 references/schema-patterns.md。2.3 shouldAnalyze必写的快速预检文档要求始终用shouldAnalyze做快速预扫描退出。其实现见 src/ast/extractor/index.ts先检查源码是否包含emotion/styled或emotion/react导入再用正则探测useTheme、styled./(、css 模板字符串及css/style等 JSX 属性用法只要命中其一即返回 true。注释明确说明允许误报false positives are acceptable目的是跳过明显与 Emotion 无关的文件为全仓库静态检查省下可观的解析开销。四、Archetype 3JSX Structural ConstraintJSX 结构约束适用场景规则要限制某个 props/插槽slot中允许出现哪些 JSX 元素——例如某些设计系统组件的 slot 只允许放入指定的子组件集合。模式组合使用 import 解析器createImportTracker与JSXAttributevisitor调用createImportTracker()创建追踪器把它的visitors合并进返回对象随后在需要处调用resolve(localName)或findLocalNames(source, name)判断某个 JSX 标识符来自哪个导入在JSXAttribute中当发现配置命中的 prop 时递归遍历其 JSX 子树逐一将元素与允许集合比对。create(context) { const importTracker createImportTracker(); return { ...importTracker.visitors, JSXAttribute(node) { // Use importTracker.resolve(displayName) to check where an element comes from // Use importTracker.findLocalNames(source, name) to find local aliases }, }; }4.1 需要处理的几种关键模式导入别名import {Foo as Bar}使Bar成为本地名importTracker.resolve(Bar)应返回{source, imported: Foo}成员表达式MenuComponents.Alert必须按${localName}.${member}的形式匹配递归穿透直接 JSX children、三元表达式、逻辑表达式、||、??、JSXExpressionContainer、JSXFragment、箭头函数体都需要继续递归透明包裹器跳过React.Fragment/Fragment命中即停遇到不允许的元素立即报告并停止递归避免重复报错。配置 schema由于允许/禁止关系通常是props × 允许元素集合的多层嵌套schema 会比较复杂文档建议以restrict-jsx-slot-childrensrc/rules/restrictJsxSlotChildren.ts为完整范式参照其配套测试见 restrictJsxSlotChildren.spec.ts。自动修复一般不安全——替换 JSX 元素需要理解组件 API 契约这超出了 AST 本身能提供的信息因此该类规则通常只报告、不做 fix。仓库对应实现createImportTracker的契约定义与单测位于 src/ast/tracker/imports.ts 与 src/ast/tracker/imports.spec.tspreferInfoText、preferStackForColumnFlex等规则同样复用了该 tracker。五、Archetype 4Template Text Analysis模板静态文本分析适用场景规则要在模板字符串的静态 CSS 文本而非插值表达式中检测模式——原始颜色值、嵌套选择器、CSS 属性名等。模式参考文档给出的推荐做法是使用createQuasiScanner按文档所述位于src/ast/scanner/index.ts它会替你完成三件事shouldAnalyze快速退出、通过getStyledCallInfo做 tag 识别、以及 quasi 迭代import {createQuasiScanner} from ../ast/scanner/index; create(context) { return createQuasiScanner(context, (cssText, quasi, info) { // cssText: the static CSS text of this quasi segment // quasi: the TemplateElement node (use for error reporting) // info: { kind: element | component | css, name?: string } for (const match of cssText.matchAll(MY_PATTERN)) { context.report({ node: quasi, messageId: ... }); } }); }scanner 会对文件中每一个 styled/css 标签模板的每个 quasi 段调用你的analyze回调并自动跳过没有 Emotion 用法的文件。说明在本仓库当前快照中src/ast/目录下仅存在extractor、tracker、utils三个子模块尚未见到文档所述的scanner目录quasi 静态文本的处理目前由 extractor/styled.ts从node.quasi.quasis[index]取 preceding quasi 文本与各规则自身的遍历承担例如 noDoubleDollarInterpolation.ts 直接遍历node.quasi.quasis、用quasi.tail判断尾段、并用quasi.range定位报告区间。迁移到统一 scanner 属于可预期的演进方向写作规则时按文档约定调用createQuasiScanner即可保持前瞻性。5.1 与 Archetype 2 的取舍这是最容易混淆的一对决策规则是目标在 CSS文本本身裸颜色、嵌套选择器、属性名→ 用createQuasiScannerArchetype 4目标是校验通过插值传给 CSS 属性的值${theme.tokens.X}→ 用createStyleCollectorArchetype 2。5.2 标签识别工具getStyledCallInfo无论走 scanner 还是自定义 visitor都可能需要先把节点归类。getStyledCallInfosrc/ast/utils/styled.ts接收一个TaggedTemplateExpression或CallExpression返回可辨识联合类型{kind: element, name, tag}styled.div/styled(div){kind: component, name, tag}styled(Component)/styled(Mod.Button){kind: css, tag}裸css或X.cssnull无法归类。分类逻辑要点见classifyTag/classifyStyledArgs含.的点号名Mod.Button一律视为 component以小写字母开头视为 HTML element否则为 componentstyled(Component).attrs({...})会被解包、递归分类内层调用同时通过isIntermediateCall跳过中间层 CallExpression如styled(X)本身确保只有最外层表达式被归类、避免同一模式被重复命中。该工具已有完整单测 src/ast/utils/styled.spec.ts。六、新规则的标准落地流程skill 流程串讲在确定原型之后SKILL.md.agents/skills/lint-new/SKILL.md给出从脚手架到注册的完整链路这里概括为三步创建文件规则本体static/oxlint/eslintPluginScraps/src/rules/$RULE_NAME.ts 同名.spec.ts测试。规则体基于ESLintUtils.RuleCreator.withoutDocsmeta中声明type: problem、schema、messages可修复规则需在meta.fixable: code中声明。命名遵循 kebab-case 规则名verb-noun如no-token-import与 camelCase 导出名。写测试用typescript-eslint/rule-tester的RuleTestervalid/invalid用例带filename可修复规则的所有 invalid 用例必须带output字段描述 autofix 后的期望代码。注册启用在 src/rules/index.ts 的rules映射中登记导出再于 eslint 配置eslint.config.ts内plugin/sentry/scraps段以sentry/scraps/$RULE_NAME: error或带 options 的数组形式启用。随后运行测试验证pnpm test-ci static/oxlint/eslintPluginScraps/src/rules/$RULE_NAME.spec.ts自动修复的边界默认立场是能修就修但以下情况不应 autofix存在多个合法修法、需人工判断取舍修复需要 AST 之外的类型信息变换会改变控制流或运行时行为修改跨越多个文件。Fixer API 常用能力lint-fix 技能中的 fix-patterns 有更细的修复范式总结replaceText、replaceTextRange、insertTextBefore/After、remove可返回单个 fix 或数组。扩展既有规则时的注意事项若修改的是配置驱动规则如use-semantic-token改动往往只在配置文件如 src/config/tokenRules.ts同时要警惕反向映射副作用——buildPropertyToRule是后写覆盖last writer wins新增类别可能改变共享属性的推荐类别需同步审视既有测试并补新用例。七、小结一张选型心法图面对新的规则诉求可以按以下顺序自问对应完整参考见 rule-archetypes.md是否只改 import 来源字符串→Archetype 1autofix 几乎零风险。是否校验动态 token/值用在了哪些 CSS 属性→Archetype 2两阶段收集 Program:exit校验类别数据下沉到 src/config/tokenRules.ts。是否限制某个 props/插槽里能放哪些 JSX 组件→Archetype 3createImportTracker定位来源 递归遍历autofix 一般不做。是否要在 CSS 静态文本里抓模式→Archetype 4扫 quasi 静态文本规则意图与 Archetype 2 恰好互补。在动手写 AST 遍历前请先到eslintPluginScraps/src/ast/检查可复用工具shouldAnalyze、getStyledCallInfo、createImportTracker、createStyleCollector等若发现多个规则共享逻辑应将其抽入src/ast/utils/。对样式体系类规则还可以进一步阅读技能包中的 style-collector-guide.md 以理解 token 收集器的内部约定对 schema 复杂的需求则参考 schema-patterns.md。这样产出的规则既贴合设计系统语义又能与 Sentry 既有 lint 基础设施无缝衔接。【免费下载链接】sentryDeveloper-first error tracking and performance monitoring项目地址: https://gitcode.com/GitHub_Trending/sen/sentry创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考