Skip to content

Experimental oxlint migration#13

Draft
AlbertSmit wants to merge 5 commits intomainfrom
experimental-oxlint-migration
Draft

Experimental oxlint migration#13
AlbertSmit wants to merge 5 commits intomainfrom
experimental-oxlint-migration

Conversation

@AlbertSmit
Copy link
Contributor

@AlbertSmit AlbertSmit commented Oct 22, 2025

Summary by CodeRabbit

  • New Features

    • Added Oxlint integration as an alternative linting tool alongside ESLint.
  • Chores

    • Added Oxlint configuration file for project-wide linting rules.
    • Updated test scripts to support both ESLint and Oxlint: test:eslint and test:oxlint.
    • Added Oxlint dependency.

@socket-security
Copy link

@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

Walkthrough

This pull request introduces Oxlint support alongside ESLint by adding Oxlint configuration, cross-linter compatibility utilities, and updating rule definitions to work with both linters through a new define-compatible-rule wrapper and defineRule API calls.

Changes

Cohort / File(s) Summary
Oxlint Configuration & Documentation
.oxlintrc.json, README.md
Added Oxlint configuration file with schema, environment presets, plugins, globals, and comprehensive ruleset; added usage instructions for oxlint experiment in README.
Core Package Configuration
package.json, index.js
Added oxlint dependency (^1.23.0); split test script into test:eslint and test:oxlint; added meta property to exported configuration in index.js.
Cross-Linter Machinery
machinery/define-compatible-rule.js, machinery/oxlint-test-runner.js
Introduced defineCompatibleRule utility that detects linter environment and transforms rules between Oxlint and ESLint formats; added test runner script for executing oxlint tests across rule directories.
AST Utilities
machinery/ast.js
Expanded JSX utilities (getJSXElementName, getParentJSXElement, isRootJSXElement, hasParentsJSXElementsWithClassName, isInJSXBranch, getParentJSXElements, isInJSXFragment, getEnclosingFunctionNode); refactored functions to use safe fallbacks instead of throwing on unknowns; added ESLint scope utilities.
Filename Utilities
machinery/filename.js
Refactored all functions to accept generic data object instead of ESLint context; added getFilename normalizer, isUniversal, and isRaw predicates; changed parameter from context-based to data-driven approach.
Rule Definitions
rules/component-properties/index.js, rules/jsx-key/index.js, rules/layout-class-name/index.js, rules/no-relative-parent-import/index.js
Wrapped rule exports with defineRule from oxlint; renamed create to createOnce handler; added null-check guards in component-properties; added ExportAllDeclaration handler in no-relative-parent-import.
Complex Rule Updates
rules/naming-policy/index.js, rules/no-default-export/index.js
Updated naming-policy to use filename-based context instead of ESLint context, added getValidRootElementClassNames helper; refactored no-default-export to use defineCompatibleRule with filename-aware checks for allowed export types (isApp, isTemplate, isUniversal, isRaw).

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Linter CLI
    participant Compat as defineCompatibleRule
    participant Detect as Environment Detection
    participant Oxlint as Oxlint Runtime
    participant ESLint as ESLint Runtime
    
    CLI->>Compat: Import rule definition
    activate Compat
    Compat->>Detect: Load environment (module init)
    activate Detect
    alt Oxlint detected
        Detect->>Detect: require('oxlint') succeeds
        Detect-->>Compat: Oxlint mode
        Compat->>Oxlint: Transform rule (meta + messages + createOnce)
        Oxlint-->>Compat: defineRule result
    else ESLint active
        Detect->>Detect: require('oxlint') fails
        Detect-->>Compat: ESLint mode
        Compat->>ESLint: Return rule unchanged
        ESLint-->>Compat: Identity result
    end
    deactivate Detect
    Compat-->>CLI: Compatible rule
    deactivate Compat
Loading
sequenceDiagram
    participant Rule as Rule Code
    participant Filename as filename.js
    participant AST as ast.js
    
    Rule->>Filename: getFilename(data)
    activate Filename
    Filename->>Filename: Check if data has getFilename()
    alt Object with method
        Filename->>Filename: Call data.getFilename()
    else Plain string
        Filename->>Filename: Return data as-is
    end
    Filename-->>Rule: filename string
    deactivate Filename
    
    Rule->>Filename: getBaseFilename(filename)
    activate Filename
    Filename->>Filename: Extract base name (remove .universal, .raw, etc.)
    Filename-->>Rule: base filename
    deactivate Filename
    
    Rule->>AST: getEnclosingFunctionNode(node, context)
    activate AST
    AST->>AST: Traverse parents until FunctionExpression/FunctionDeclaration/ArrowFunction
    AST-->>Rule: function node
    deactivate AST
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

The changes introduce a substantial cross-linter compatibility layer with heterogeneous modifications: new utility functions with expanded scope (ast.js, define-compatible-rule.js), refactored function signatures shifting from context-based to data-driven patterns (filename.js), and systematic rule wrapping with defineRule across multiple files. While many rule updates follow a consistent pattern, the logic density in naming-policy and no-default-export requires separate reasoning. The machinery layer changes demand careful analysis of environment detection and rule transformation logic.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Experimental oxlint migration" accurately and specifically describes the primary change in this pull request. The changeset comprehensively introduces oxlint support, including a new oxlint configuration file, cross-linter compatibility utilities, updates to multiple rule files to use oxlint's API, the oxlint dependency, and a test runner for oxlint. The title clearly conveys the main objective to a developer scanning the repository history, and while it doesn't enumerate every detail, it appropriately summarizes the overarching purpose of the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch experimental-oxlint-migration

Comment @coderabbitai help to get the list of available commands and usage tips.

@AlbertSmit
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
rules/component-properties/index.js (1)

20-20: Inconsistency: create vs createOnce across rules.

This rule uses create(context) while rules/layout-class-name/index.js uses createOnce(context). Ensure this difference is intentional and both are valid for the oxlint/ESLint compatibility layer being built.

rules/no-relative-parent-import/index.js (1)

1-31: This rule hard‑depends on Oxlint; ESLint will crash. Switch to the compatibility wrapper.

Importing oxlint directly breaks ESLint environments. Use the shared defineCompatibleRule and create (ESLint) with messageId/data so Oxlint mapping works.

Apply this diff:

-const { defineRule } = require("oxlint")
+const { defineCompatibleRule } = require("../../machinery/define-compatible-rule")

-const messages = {
-  'no relative parent import': found =>
-    `Unexpected relative parent import '${found}' - use a root slash import`,
-}
-
-module.exports = defineRule({
-  messages,
+module.exports = defineCompatibleRule({
   messages,
 
-  meta: { type: 'problem' },
+  meta: {
+    type: 'problem',
+    messages: {
+      noRelativeParentImport: "Unexpected relative parent import '{{found}}' - use a root slash import"
+    },
+    schema: []
+  },
 
-  createOnce(context) {
+  create(context) {
     return {
       'ImportDeclaration': reportRelativeImportInSource,
       'ExportNamedDeclaration': reportRelativeImportInSource,
       'ExportAllDeclaration': reportRelativeImportInSource,
     }
 
     function reportRelativeImportInSource({ source }) {
       if (!source) return
       const { value } = source
-      if (!value.includes('..')) return
+      // Only match dot-dot segments as full path components
+      if (!/(^|\/)\.\.(\/|$)/.test(value)) return
 
-      context.report({
-        message: messages['no relative parent import'](value),
-        node: source
-      })
+      context.report({
+        node: source,
+        messageId: 'noRelativeParentImport',
+        data: { found: value },
+      })
     }
   }
-})
+})
rules/naming-policy/index.js (2)

75-87: Align getBaseFilename usage with the new helpers.

Mixed signatures: here getBaseFilename(context) vs elsewhere getBaseFilename(filename). Use getFilename(context) first, then pass filename.

-      const name = getBaseFilename(context)
+      const filename = getFilename(context)
+      const name = getBaseFilename(filename)
       const expected = `./${name}.css`

Also applies to: 93-95


26-28: Fix typos in user-facing messages.

Minor but user-visible.

-  'invalid styles variable name': (found, expected) =>
-    `Unexptected css import name '${found}', expected '${expected}'`,
+  'invalid styles variable name': (found, expected) =>
+    `Unexpected css import name '${found}', expected '${expected}'`,
@@
-  'ref should end with Ref': (found, exptected) =>
-    `Unexpected ref name '${found}', expected '${exptected}'`,
+  'ref should end with Ref': (found, expected) =>
+    `Unexpected ref name '${found}', expected '${expected}'`,

Also applies to: 33-35

♻️ Duplicate comments (2)
rules/component-properties/index.js (1)

1-1: Critical: oxlint package doesn't export defineRule.

Same issue as in rules/layout-class-name/index.js - oxlint is a CLI tool and doesn't provide a Node.js defineRule export. This import will fail at runtime.

rules/jsx-key/index.js (1)

3-3: Critical: oxlint package doesn't export defineRule.

Same critical issue - this import from 'oxlint' will fail. All custom rules need to be updated to use the correct compatibility layer or mechanism for loading custom rules into oxlint.

🧹 Nitpick comments (2)
package.json (1)

24-24: Move oxlint to devDependencies.

oxlint is a development tool (linter) and should be in devDependencies rather than dependencies to avoid including it in production installations. Version 1.23.0 is current and valid on npm.

rules/naming-policy/index.js (1)

70-72: Verify selector for hooks returning refs.

Current selector may miss the common CallExpression form (e.g., const x = useDomRef()). Consider matching the callee Identifier under CallExpression.

Possible alternative:

// Match: const fooRef = useSomethingRef()
"VariableDeclarator > .init CallExpression > .callee Identifier[name=/^use.*Ref$/]"

Please confirm with tests that your selector hits intended cases and doesn’t fire on bare assignments like const x = useDomRef. Want a quick script to scan the repo for call sites?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 214dcc3 and d188fa5.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (14)
  • .oxlintrc.json (1 hunks)
  • README.md (1 hunks)
  • index.js (1 hunks)
  • machinery/ast.js (2 hunks)
  • machinery/define-compatible-rule.js (1 hunks)
  • machinery/filename.js (1 hunks)
  • machinery/oxlint-test-runner.js (1 hunks)
  • package.json (2 hunks)
  • rules/component-properties/index.js (3 hunks)
  • rules/jsx-key/index.js (3 hunks)
  • rules/layout-class-name/index.js (3 hunks)
  • rules/naming-policy/index.js (6 hunks)
  • rules/no-default-export/index.js (1 hunks)
  • rules/no-relative-parent-import/index.js (2 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
machinery/ast.js

[error] 22-22: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

.oxlintrc.json

[error] 1-25: JSON standard does not allow comments.

(parse)


[error] 28-30: Expected a property but instead found '// Environments → same semantics as ESLint'.

Expected a property here.

(parse)


[error] 25-28: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 28-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-30: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 30-37: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 37-38: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 38-38: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 38-38: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 38-41: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 41-41: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 41-42: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 42-42: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 42-44: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 44-46: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 46-46: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 46-46: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 46-53: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 53-53: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 53-53: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 53-53: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 53-54: Expected a property but instead found '// Core "correctness/suspicious/pedantic" rules (supported by Oxlint)'.

Expected a property here.

(parse)


[error] 53-53: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 53-54: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 54-55: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 55-55: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 55-55: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 55-55: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 56-56: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 56-56: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 56-56: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 56-56: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 56-57: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 57-57: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 57-57: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 57-57: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 58-58: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 58-58: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 58-58: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 58-58: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 58-59: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 59-59: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 59-59: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 59-59: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 59-60: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 60-60: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 60-60: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 60-60: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 60-61: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 61-61: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 61-61: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 61-61: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 61-62: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 62-62: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 62-62: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 62-62: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 62-63: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 63-63: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 63-63: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 63-63: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 63-64: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 64-64: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 64-64: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 64-64: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 64-65: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 65-65: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 65-65: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 65-65: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 65-66: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 66-66: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 66-66: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 66-66: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 66-67: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 67-67: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 67-67: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 67-67: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 67-68: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 68-68: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 68-68: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 68-68: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 68-69: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 69-69: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 69-69: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 69-69: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 69-70: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 70-70: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 70-70: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 70-70: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 70-71: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 71-71: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 71-71: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 71-71: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 72-72: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 72-72: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 72-72: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 72-72: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 72-73: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 73-73: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 73-73: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 73-73: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 73-74: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 74-74: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 74-74: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 74-74: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 74-75: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 75-75: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 75-75: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 75-75: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 75-76: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 76-76: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 76-76: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 76-76: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 76-77: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 77-77: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 77-77: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 77-77: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 77-78: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 78-78: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 78-78: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 78-78: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 78-79: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 79-79: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 79-79: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 79-79: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 79-80: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 80-80: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 80-80: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 80-80: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 80-81: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 81-81: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 81-81: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 81-81: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 81-82: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 82-82: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 82-82: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 82-82: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 82-83: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 83-83: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 83-83: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 83-83: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 83-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-84: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 84-85: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 85-85: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 85-86: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 86-86: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 86-86: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 86-86: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 86-87: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 87-87: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 87-87: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 87-87: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 87-88: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 88-88: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 88-88: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 88-88: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 89-89: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 89-89: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 89-89: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 89-89: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 89-90: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 90-90: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 90-90: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 90-90: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 90-91: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 91-91: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 91-91: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 91-91: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 91-92: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 92-92: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 92-92: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 92-92: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 92-93: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 93-93: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 93-93: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 93-93: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 93-94: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 94-94: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 94-94: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 94-94: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 94-95: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 95-95: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 95-95: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 95-95: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 95-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-96: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 96-97: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 97-97: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 97-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-98: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 98-99: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 99-99: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 99-100: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 100-100: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 100-100: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 100-100: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 100-101: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 101-101: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 101-101: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 101-101: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 101-102: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 102-102: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 102-102: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 102-102: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 103-103: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 103-103: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 103-103: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 103-103: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 104-104: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 104-104: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 104-104: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 104-104: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 104-105: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 105-105: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 105-105: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 105-105: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 106-106: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 106-106: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 106-106: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 106-106: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 106-108: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 108-108: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 108-108: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 108-109: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 109-111: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 111-111: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 111-114: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 114-115: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 115-116: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 116-116: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 116-116: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 116-116: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 116-117: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 117-117: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 117-117: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 117-117: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 117-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-118: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 118-119: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 119-119: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 119-120: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 120-120: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 120-120: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 120-120: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 120-121: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 121-121: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 121-121: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 121-121: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 121-122: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 122-122: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 122-122: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 122-129: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 129-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-130: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 130-131: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 131-131: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 131-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-132: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 132-133: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 133-134: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 134-135: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 135-135: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 135-135: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 135-135: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 135-136: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 136-136: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 136-136: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 136-136: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 136-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-137: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 137-138: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 138-138: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 138-139: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 139-139: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 139-139: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 139-139: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 139-140: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 140-140: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 140-140: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 140-140: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 140-141: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 141-141: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 141-141: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 141-141: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 141-142: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 142-142: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 142-142: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 142-143: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 143-144: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 144-144: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 144-144: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 144-144: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 144-146: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 146-146: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 146-146: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 146-147: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 147-148: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 148-148: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 148-148: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 148-148: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 148-149: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 149-149: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 149-149: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 149-149: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 149-150: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 150-150: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 150-150: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 150-150: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 150-151: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 151-151: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 151-151: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 151-151: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 151-152: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 152-152: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 152-152: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 152-152: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 152-153: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 153-153: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 153-153: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 153-153: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 153-154: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 154-154: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 154-154: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 154-154: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 154-155: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 155-155: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 155-155: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 155-155: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 155-156: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 156-156: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 156-156: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 156-156: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 156-157: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 157-157: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 157-157: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 157-157: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 157-158: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 158-158: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 158-158: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 158-158: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 158-159: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 159-159: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 159-159: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 159-159: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 159-160: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 160-160: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 160-160: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 160-160: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 160-161: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 161-161: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 161-161: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 161-161: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 161-162: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 162-162: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 162-162: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 162-162: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 162-163: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 163-163: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 163-163: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 163-163: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 163-165: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 165-165: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 165-165: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 165-166: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 166-167: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 167-167: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 167-167: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 167-167: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 167-168: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 168-168: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 168-168: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 168-168: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 168-169: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 169-169: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 169-169: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 169-169: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 169-170: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 170-170: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 170-170: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 170-170: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 170-171: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 171-171: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 171-171: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)


[error] 171-171: End of file expected

Use an array for a sequence of values: [1, 2]

(parse)

🔇 Additional comments (9)
README.md (1)

6-19: LGTM: Clear experimental usage documentation.

The usage instructions appropriately document the experimental oxlint workflow, including the necessary installation steps and script configuration.

index.js (1)

2-4: LGTM: Standard plugin metadata.

Adding the meta property with the plugin name follows ESLint plugin conventions and enables proper plugin identification.

.oxlintrc.json (3)

1-22: Note: Static analysis warnings are false positives.

The Biome errors about JSON not supporting comments can be safely ignored. Oxlint's configuration format supports JSON with Comments (JSONC), similar to tsconfig.json and other common configuration files. The inline comments provide valuable documentation for the migration.


40-42: jsPlugins is supported but has important limitations.

jsPlugins is a documented and supported configuration option in oxlint. However, be aware that JS plugins are experimental and not subject to semver, and they are not supported in language server at present. If you depend on language server features or stability guarantees, consider the implications of these limitations.


165-172: Custom Kaliber rules are properly configured to work with oxlint.

Oxlint supports loading custom JavaScript ESLint-compatible plugins via jsPlugins configuration. The .oxlintrc.json correctly specifies "jsPlugins": ["./index.js"], and ./index.js is a valid ESLint plugin module that exports all six Kaliber rules with proper meta information and rule implementations. The configuration will work as intended.

package.json (1)

4-5: LGTM: Test scripts properly separated.

The split between test:eslint and test:oxlint allows testing both linters independently during the migration experiment.

rules/layout-class-name/index.js (2)

33-33: Verify createOnce vs create naming.

The method is renamed from create to createOnce. Confirm this is the correct API for oxlint's custom rule system, as this differs from ESLint's standard create method.


7-7: The review comment is incorrect.

The oxlint package does export defineRule. The import statement on line 7 is valid and will not fail at runtime. No action is required.

Likely an incorrect or invalid review comment.

rules/component-properties/index.js (1)

82-89: LGTM: Defensive null check added.

The added null check name && on line 84 prevents potential errors if name is undefined or null, improving the robustness of the isSetter function.

Comment on lines 21 to +26
case 'TemplateLiteral':
const [name] = property.quasis
return name.value.raw
default: throw new Error(`Can not determine name for '${property.type}'`)
default:
// DO NOT THROW - This can panic linters like Oxlint
return '???'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Wrap const in switch case to avoid cross‑case scope leakage.

Fixes Biome’s noSwitchDeclarations and prevents accidental access from other cases.

Apply this diff:

-    case 'TemplateLiteral':
-      const [name] = property.quasis
-      return name.value.raw
+    case 'TemplateLiteral': {
+      const [name] = property.quasis
+      return name.value.raw
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case 'TemplateLiteral':
const [name] = property.quasis
return name.value.raw
default: throw new Error(`Can not determine name for '${property.type}'`)
default:
// DO NOT THROW - This can panic linters like Oxlint
return '???'
case 'TemplateLiteral': {
const [name] = property.quasis
return name.value.raw
}
default:
// DO NOT THROW - This can panic linters like Oxlint
return '???'
🧰 Tools
🪛 Biome (2.1.2)

[error] 22-22: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🤖 Prompt for AI Agents
In machinery/ast.js around lines 21 to 26, the `const [name] = property.quasis`
is declared directly in a switch case which can cause cross-case scope leakage
and triggers Biome’s noSwitchDeclarations; fix it by wrapping the
'TemplateLiteral' case body in braces (a block) so the const is scoped to that
case, keep the existing return inside the block, and leave the default branch
unchanged.

Comment on lines +113 to +138
function getFunctionName(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') getESLintScope(contextOrNode)

// --- NEW OXLINT/NODE LOGIC ---
const functionNode = contextOrNode
if (!functionNode) return '???'

// Case 1: function MyComponent() {}
if (functionNode.id && functionNode.id.type === 'Identifier') {
return functionNode.id.name
}

// Case 2: const MyComponent = () => {}
// Case 3: const MyComponent = function() {}
if (
(functionNode.type === 'ArrowFunctionExpression' || functionNode.type === 'FunctionExpression') &&
functionNode.parent &&
functionNode.parent.type === 'VariableDeclarator' &&
functionNode.parent.id.type === 'Identifier'
) {
return functionNode.parent.id.name
}

return '???'
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

getFunctionName ignores ESLint context; always returns '???' in that path.

Return the scope‑derived name when a context is passed.

Apply this diff:

 function getFunctionName(contextOrNode) {
   // Check if we got the ESLint 'context' object by sniffing for .getScope()
-  if (typeof contextOrNode.getScope === 'function') getESLintScope(contextOrNode)
+  if (typeof contextOrNode.getScope === 'function') {
+    return getESLintScope(contextOrNode)
+  }
 
   // --- NEW OXLINT/NODE LOGIC ---
   const functionNode = contextOrNode
   if (!functionNode) return '???'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function getFunctionName(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') getESLintScope(contextOrNode)
// --- NEW OXLINT/NODE LOGIC ---
const functionNode = contextOrNode
if (!functionNode) return '???'
// Case 1: function MyComponent() {}
if (functionNode.id && functionNode.id.type === 'Identifier') {
return functionNode.id.name
}
// Case 2: const MyComponent = () => {}
// Case 3: const MyComponent = function() {}
if (
(functionNode.type === 'ArrowFunctionExpression' || functionNode.type === 'FunctionExpression') &&
functionNode.parent &&
functionNode.parent.type === 'VariableDeclarator' &&
functionNode.parent.id.type === 'Identifier'
) {
return functionNode.parent.id.name
}
return '???'
}
function getFunctionName(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') {
return getESLintScope(contextOrNode)
}
// --- NEW OXLINT/NODE LOGIC ---
const functionNode = contextOrNode
if (!functionNode) return '???'
// Case 1: function MyComponent() {}
if (functionNode.id && functionNode.id.type === 'Identifier') {
return functionNode.id.name
}
// Case 2: const MyComponent = () => {}
// Case 3: const MyComponent = function() {}
if (
(functionNode.type === 'ArrowFunctionExpression' || functionNode.type === 'FunctionExpression') &&
functionNode.parent &&
functionNode.parent.type === 'VariableDeclarator' &&
functionNode.parent.id.type === 'Identifier'
) {
return functionNode.parent.id.name
}
return '???'
}
🤖 Prompt for AI Agents
In machinery/ast.js around lines 113 to 138, the function currently calls
getESLintScope(context) when an ESLint context is detected but ignores its
return value and proceeds to node-only logic, causing it to return '???' for
context paths; change the flow so that when contextOrNode appears to be an
ESLint context (has getScope), capture the name returned by getESLintScope and
if it yields a non-empty function name return that immediately instead of
falling through to the node logic; otherwise continue with the existing node
checks (Identifier id, VariableDeclarator parents) and return '???' as the final
fallback.

Comment on lines +140 to +147
function getESLintExportType(context) {
try {
const { type } = getRootFunctionScope_Old(context.getScope()).block.parent
return ['ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(type)
} catch (e) {
return false
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

getESLintExportType references an undefined helper.

Use getESLintRootFunctionScope (the function defined below).

Apply this diff:

 function getESLintExportType(context) {  
     try {
-      const { type } = getRootFunctionScope_Old(context.getScope()).block.parent
+      const { type } = getESLintRootFunctionScope(context.getScope()).block.parent
       return ['ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(type)
     } catch (e) {
       return false 
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function getESLintExportType(context) {
try {
const { type } = getRootFunctionScope_Old(context.getScope()).block.parent
return ['ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(type)
} catch (e) {
return false
}
}
function getESLintExportType(context) {
try {
const { type } = getESLintRootFunctionScope(context.getScope()).block.parent
return ['ExportDefaultDeclaration', 'ExportNamedDeclaration'].includes(type)
} catch (e) {
return false
}
}
🤖 Prompt for AI Agents
In machinery/ast.js around lines 140 to 147, getESLintExportType currently calls
the undefined helper getRootFunctionScope_Old; replace that call with the
existing getESLintRootFunctionScope (defined below) so the function reads the
root scope from getESLintRootFunctionScope(context.getScope()) and uses
.block.parent as before; ensure no other references to getRootFunctionScope_Old
remain and that getESLintRootFunctionScope is in scope (no import/change needed
if it’s defined later in the file).

Comment on lines +149 to +152
function isInExport(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') getESLintExportType(contextOrNode)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

isInExport ignores the ESLint‑context branch result.

Short‑circuit with the ESLint check when a context is provided.

Apply this diff:

 function isInExport(contextOrNode) {
   // Check if we got the ESLint 'context' object by sniffing for .getScope()
-  if (typeof contextOrNode.getScope === 'function') getESLintExportType(contextOrNode)
+  if (typeof contextOrNode.getScope === 'function') {
+    return getESLintExportType(contextOrNode)
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function isInExport(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') getESLintExportType(contextOrNode)
function isInExport(contextOrNode) {
// Check if we got the ESLint 'context' object by sniffing for .getScope()
if (typeof contextOrNode.getScope === 'function') {
return getESLintExportType(contextOrNode)
}
🤖 Prompt for AI Agents
In machinery/ast.js around lines 149 to 152, the isInExport function calls
getESLintExportType(contextOrNode) when given an ESLint context but does not use
or return its result; change the branch to short-circuit and return the result
of getESLintExportType(contextOrNode) when typeof contextOrNode.getScope ===
'function' so the ESLint-context path correctly propagates the computed export
status.

Comment on lines +15 to +32
function detectLinterEnv() {
try {
// 1. Try to require 'oxlint'. If it works, we're in Oxlint.
const { defineRule } = require('oxlint');
return {
name: 'oxlint',
define: defineRule,
};
} catch (e) {
// 2. If it fails, we're in ESLint.
return {
name: 'eslint',
// For ESLint, the "define" function is just an identity function.
// It returns the rule object as-is, which is what ESLint expects.
define: (rule) => rule,
};
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Environment detection may misclassify when both ESLint and Oxlint are installed.

Presence‑based require('oxlint') can select Oxlint while running under ESLint, exporting an incompatible shape. Gate on an explicit env hint and fall back to ESLint.

Apply this diff:

-function detectLinterEnv() {
-  try {
-    // 1. Try to require 'oxlint'. If it works, we're in Oxlint.
-    const { defineRule } = require('oxlint');
-    return {
-      name: 'oxlint',
-      define: defineRule,
-    };
-  } catch (e) {
-    // 2. If it fails, we're in ESLint.
-    return {
-      name: 'eslint',
-      // For ESLint, the "define" function is just an identity function.
-      // It returns the rule object as-is, which is what ESLint expects.
-      define: (rule) => rule,
-    };
-  }
-}
+function detectLinterEnv() {
+  const envHint = process.env.OXLINT === '1' || process.env.LINTER === 'oxlint'
+  if (!envHint) {
+    return { name: 'eslint', define: (rule) => rule }
+  }
+  try {
+    const { defineRule } = require('oxlint')
+    return { name: 'oxlint', define: defineRule }
+  } catch {
+    return { name: 'eslint', define: (rule) => rule }
+  }
+}
🤖 Prompt for AI Agents
In machinery/define-compatible-rule.js around lines 15 to 32, environment
detection currently infers Oxlint by simply requiring 'oxlint', which can
misclassify when both linters are installed; change the logic to first check an
explicit environment hint (e.g., process.env.LINTER === 'oxlint' or
process.env.OXLINT === 'true') and only attempt to require('oxlint') when the
hint requests Oxlint, otherwise default to the ESLint-compatible identity define
function; if the env hint requests Oxlint but the require fails, fall back to
returning the ESLint shape (and optionally surface a debug log), ensuring the
default behavior is safe for ESLint when both packages are present.

Comment on lines +21 to 24
function isPage(data) {
const filename = getFilename(data)
return /.+\/pages\/[^/]+\.js/.test(filename)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Null‑safety and Windows paths.

  • isUniversal/isRaw call .endsWith on possibly undefined filenames.
  • isPage regex won’t match Windows \ paths.

Apply this diff:

 function isPage(data) {
-  const filename = getFilename(data)
-  return /.+\/pages\/[^/]+\.js/.test(filename)
+  const filename = getFilename(data)
+  const normalized = typeof filename === 'string' ? filename.replace(/\\/g, '/') : ''
+  return /.+\/pages\/[^/]+\.js/.test(normalized)
 }
 
 function isUniversal(data) {
   const filename = getFilename(data)
-  return filename.endsWith('.universal.js')
+  return !!filename && filename.endsWith('.universal.js')
 }
 
 function isRaw(data) {
   const filename = getFilename(data)
-  return filename.endsWith('.raw.js')
+  return !!filename && filename.endsWith('.raw.js')
 }

Optionally make getFilename always return a string to simplify callers:

-  else return data
+  else return typeof data === 'string' ? data : ''

Also applies to: 31-39

🤖 Prompt for AI Agents
In machinery/filename.js around lines 21-24 and 31-39, callers call .endsWith on
possibly undefined filenames and the isPage regex only matches POSIX separators;
ensure getFilename always returns a string (at minimum an empty string) and
normalize path separators to '/' (e.g. replace backslashes) so callers can rely
on a string; update isPage to test against the normalized filename and change
isUniversal/isRaw to defensively check filename truthiness before calling
.endsWith (or use optional chaining) so we never call .endsWith on undefined.

Comment on lines +10 to +29
fs.readdirSync(rulesDir).forEach(rule => {
const ruleDir = path.resolve(rulesDir, rule);
const testFile = path.resolve(ruleDir, 'test.js');
if (fs.existsSync(testFile)) {
console.log(`Running tests for ${rule}...`);
const oxlint = spawn(oxlintPath, ['--config', '.oxlintrc.json', testFile]);

oxlint.stdout.on('data', (data) => {
console.log(data.toString());
});

oxlint.stderr.on('data', (data) => {
console.error(data.toString());
});

oxlint.on('close', (code) => {
console.log(`Tests for ${rule} finished with code ${code}`);
});
}
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix: Test runner exits before tests complete.

The script spawns oxlint processes asynchronously within forEach but doesn't wait for them to complete. The script will exit immediately after spawning all processes, potentially before any tests finish. Additionally, there's no error handling if the oxlint binary doesn't exist.

Apply this approach to properly await all test processes:

-fs.readdirSync(rulesDir).forEach(rule => {
+const tests = [];
+
+fs.readdirSync(rulesDir).forEach(rule => {
   const ruleDir = path.resolve(rulesDir, rule);
   const testFile = path.resolve(ruleDir, 'test.js');
   if (fs.existsSync(testFile)) {
     console.log(`Running tests for ${rule}...`);
-    const oxlint = spawn(oxlintPath, ['--config', '.oxlintrc.json', testFile]);
+    
+    const testPromise = new Promise((resolve, reject) => {
+      const oxlint = spawn(oxlintPath, ['--config', '.oxlintrc.json', testFile]);
 
-    oxlint.stdout.on('data', (data) => {
-      console.log(data.toString());
-    });
+      oxlint.stdout.on('data', (data) => {
+        console.log(data.toString());
+      });
 
-    oxlint.stderr.on('data', (data) => {
-      console.error(data.toString());
-    });
+      oxlint.stderr.on('data', (data) => {
+        console.error(data.toString());
+      });
 
-    oxlint.on('close', (code) => {
-      console.log(`Tests for ${rule} finished with code ${code}`);
+      oxlint.on('close', (code) => {
+        console.log(`Tests for ${rule} finished with code ${code}`);
+        if (code !== 0) reject(new Error(`Tests failed for ${rule}`));
+        else resolve();
+      });
+      
+      oxlint.on('error', (err) => {
+        reject(new Error(`Failed to run oxlint: ${err.message}`));
+      });
     });
+    
+    tests.push(testPromise);
   }
-});
+});
+
+Promise.all(tests)
+  .then(() => {
+    console.log('All tests completed successfully');
+    process.exit(0);
+  })
+  .catch((err) => {
+    console.error(err.message);
+    process.exit(1);
+  });
🤖 Prompt for AI Agents
In machinery/oxlint-test-runner.js around lines 10 to 29, the script spawns
oxlint processes inside a forEach without awaiting them and doesn't check for
the oxlint binary; fix by converting the loop to collect Promises for each
spawned process, verify oxlintPath exists before spawning (throw or log and exit
if missing), create a Promise for each child process that pipes stdout/stderr
and resolves/rejects on 'close'/'error' with the exit code, then await
Promise.all on that array and exit with a non-zero code if any child failed;
ensure any spawn errors are caught and logged.

@@ -1,10 +1,12 @@
const { defineRule } = require('oxlint')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Don’t import Oxlint directly; use the compatibility wrapper.

Directly requiring 'oxlint' breaks ESLint usage and defeats the cross‑linter goal. Import defineRule from the compatibility module instead; keep createOnce if the wrapper supports it.

-const { defineRule } = require('oxlint')
+const { defineRule } = require('../../machinery/define-compatible-rule')

Also applies to: 37-42

🤖 Prompt for AI Agents
In rules/naming-policy/index.js at line 1 (and similarly for lines 37-42), the
file imports defineRule directly from 'oxlint', which breaks ESLint usage and
bypasses the compatibility wrapper; change the import to use the project's
compatibility module (e.g., require the wrapper that re-exports defineRule and
createOnce), replace require('oxlint') with require of the compatibility
wrapper, and keep createOnce usage if the wrapper supports it so the rule works
across linters.

Comment on lines 121 to 124
function reportInvalidRootElementClassName(jsxElement, property) {
const expectedClassNames = getValidRootElementClassNames(context)
const functionNode = getEnclosingFunctionNode(jsxElement);
const expectedClassNames = getValidRootElementClassNames(context, functionNode)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Null-safety for functionNode and escape base in RegExp.

getEnclosingFunctionNode can be null; calling getFunctionName/isInExport would throw. Also escape regex metacharacters in base filename.

-function getValidRootElementClassNames(context, functionNode) {
-  const filename = getFilename(context)
-  const prefix = new RegExp(`^${getBaseFilename(filename)}`)
-
-  const name = getFunctionName(functionNode).replace(prefix, '')
-  const exported = isInExport(functionNode)
+function getValidRootElementClassNames(context, functionNode) {
+  const filename = getFilename(context)
+  const base = getBaseFilename(filename)
+  const prefix = new RegExp(`^${base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`)
+
+  const fnName = functionNode ? getFunctionName(functionNode) : ''
+  const name = (fnName || '').replace(prefix, '')
+  const exported = functionNode ? isInExport(functionNode) : false

Also applies to: 183-195

🤖 Prompt for AI Agents
In rules/naming-policy/index.js around lines 121-124 (and similarly 183-195),
getEnclosingFunctionNode may return null which leads to calling getFunctionName
or isInExport on null; guard against that by checking functionNode before using
it (e.g., return early or use a safe fallback) so you never call methods on
null, and ensure expectedClassNames is computed only when functionNode exists;
additionally, when building a RegExp from the file base name escape regex
metacharacters in the base filename (use a regex-escape helper) before
constructing the RegExp to avoid unintended pattern matches.

Comment on lines +19 to +26
for (const specifier of node.specifiers) {
if (specifier.exported.name === 'default') {
context.report({
node: specifier,
messageId: 'noDefaultExport',
})
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Catch export { default as X } too, not only export { default }.

Current check only looks at specifier.exported.name === 'default'. It misses cases where default is re‑exported under another name. Check both exported and local.

Apply this diff:

-      for (const specifier of node.specifiers) {
-        if (specifier.exported.name === 'default') {
-          context.report({
-            node: specifier,
-            messageId: 'noDefaultExport',
-          })
-        }
-      }
+      for (const specifier of node.specifiers) {
+        const exported = specifier.exported && specifier.exported.name
+        const local = specifier.local && specifier.local.name
+        if (exported === 'default' || local === 'default') {
+          context.report({
+            node: specifier,
+            messageId: 'noDefaultExport',
+          })
+        }
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const specifier of node.specifiers) {
if (specifier.exported.name === 'default') {
context.report({
node: specifier,
messageId: 'noDefaultExport',
})
}
}
for (const specifier of node.specifiers) {
const exported = specifier.exported && specifier.exported.name
const local = specifier.local && specifier.local.name
if (exported === 'default' || local === 'default') {
context.report({
node: specifier,
messageId: 'noDefaultExport',
})
}
}
🤖 Prompt for AI Agents
In rules/no-default-export/index.js around lines 19 to 26, the current loop only
checks specifier.exported.name === 'default' and misses re-exports like "export
{ default as X }"; update the check to detect either specifier.exported.name ===
'default' OR specifier.local && specifier.local.name === 'default' (or
equivalent safe property access) and call context.report when either is true so
both direct default exports and aliased default re-exports are caught.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments