Repository: ota-meshi/eslint-plugin-astro
Pull request #130 (2022-10-31 07:18:37)

feat: add `astro/valid-compile` rule

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: da8fe260b6cad8fa45031925d2a54779dc03a4f4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/ota-meshi/eslint-plugin-astro/new/valid-compile?filename=.changeset/five-lions-return.md&value=---%0A%22eslint-plugin-astro%22%3A%20patch%0A---%0A%0Afeat%3A%20add%20%60astro%2Fvalid-compile%60%20rule%0A)



Patch:
diff --git a/.changeset/five-lions-return.md b/.changeset/five-lions-return.md
new file mode 100644
index 0000000..ddb4c33
--- /dev/null
+++ b/.changeset/five-lions-return.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-astro": minor
+---
+
+feat: add `astro/valid-compile` rule
diff --git a/.changeset/purple-pumpkins-compare.md b/.changeset/purple-pumpkins-compare.md
new file mode 100644
index 0000000..0873d85
--- /dev/null
+++ b/.changeset/purple-pumpkins-compare.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-astro": minor
+---
+
+BREAKING: add `astro/valid-compile` rule to recommended config
diff --git a/.changeset/silly-berries-stare.md b/.changeset/silly-berries-stare.md
new file mode 100644
index 0000000..a0f4bde
--- /dev/null
+++ b/.changeset/silly-berries-stare.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-astro": minor
+---
+
+feat: update astro-eslint-parser to v0.9
diff --git a/README.md b/README.md
index 229f98e..ef0e9c5 100644
--- a/README.md
+++ b/README.md
@@ -251,6 +251,7 @@ These rules relate to possible syntax or logic errors in Astro component code:
 | [astro/no-deprecated-astro-fetchcontent](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-fetchcontent/) | disallow using deprecated `Astro.fetchContent()` | :star::wrench: |
 | [astro/no-deprecated-astro-resolve](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-resolve/) | disallow using deprecated `Astro.resolve()` | :star: |
 | [astro/no-unused-define-vars-in-style](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-unused-define-vars-in-style/) | disallow unused `define:vars={...}` in `style` tag | :star: |
+| [astro/valid-compile](https://ota-meshi.github.io/eslint-plugin-astro/rules/valid-compile/) | disallow warnings when compiling. | :star: |
 
 ## Security Vulnerability
 
diff --git a/docs/rules.md b/docs/rules.md
index 361c2b0..7de17f2 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -18,6 +18,7 @@ These rules relate to possible syntax or logic errors in Astro component code:
 | [astro/no-deprecated-astro-fetchcontent](./rules/no-deprecated-astro-fetchcontent.md) | disallow using deprecated `Astro.fetchContent()` | :star::wrench: |
 | [astro/no-deprecated-astro-resolve](./rules/no-deprecated-astro-resolve.md) | disallow using deprecated `Astro.resolve()` | :star: |
 | [astro/no-unused-define-vars-in-style](./rules/no-unused-define-vars-in-style.md) | disallow unused `define:vars={...}` in `style` tag | :star: |
+| [astro/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | :star: |
 
 ## Security Vulnerability
 
diff --git a/docs/rules/valid-compile.md b/docs/rules/valid-compile.md
new file mode 100644
index 0000000..27fc630
--- /dev/null
+++ b/docs/rules/valid-compile.md
@@ -0,0 +1,48 @@
+---
+title: "astro/valid-compile"
+description: "disallow warnings when compiling."
+---
+
+# astro/valid-compile
+
+> disallow warnings when compiling.
+
+- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
+- :gear: This rule is included in `"plugin:astro/recommended"`.
+
+## :book: Rule Details
+
+This rule uses `@astrojs/compiler` to check the source code.
+
+<ESLintCodeBlock>
+
+<!--eslint-skip-->
+
+```astro
+---
+/* eslint astro/valid-compile: "error" */
+---
+
+{/* ✗ BAD */}
+<p set:html="string">string</p>
+```
+
+</ESLintCodeBlock>
+
+## :wrench: Options
+
+Nothing.
+
+## :books: Further Reading
+
+## :couple: Related Rules
+
+- [astro/no-conflict-set-directives]
+
+[astro/no-conflict-set-directives]: ./no-conflict-set-directives.md
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/src/rules/valid-compile.ts)
+- [Test source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/tests/src/rules/valid-compile.ts)
+- [Test fixture sources](https://github.com/ota-meshi/eslint-plugin-astro/tree/main/tests/fixtures/rules/valid-compile)
diff --git a/package.json b/package.json
index 6d09671..4a16349 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
   "homepage": "https://ota-meshi.github.io/eslint-plugin-astro/",
   "dependencies": {
     "@typescript-eslint/types": "^5.25.0",
-    "astro-eslint-parser": "^0.7.0",
+    "astro-eslint-parser": "^0.9.0",
     "eslint-utils": "^3.0.0",
     "postcss": "^8.4.14",
     "postcss-selector-parser": "^6.0.10",
diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts
index bf699c5..067cb84 100644
--- a/src/configs/recommended.ts
+++ b/src/configs/recommended.ts
@@ -11,5 +11,6 @@ export = {
     "astro/no-deprecated-astro-fetchcontent": "error",
     "astro/no-deprecated-astro-resolve": "error",
     "astro/no-unused-define-vars-in-style": "error",
+    "astro/valid-compile": "error",
   },
 }
diff --git a/src/rules/valid-compile.ts b/src/rules/valid-compile.ts
new file mode 100644
index 0000000..ef21704
--- /dev/null
+++ b/src/rules/valid-compile.ts
@@ -0,0 +1,36 @@
+import { createRule } from "../utils"
+
+export default createRule("valid-compile", {
+  meta: {
+    docs: {
+      description: "disallow warnings when compiling.",
+      category: "Possible Errors",
+      recommended: true,
+    },
+    schema: [],
+    messages: {},
+    type: "problem",
+  },
+  create(context) {
+    if (!context.parserServices.getAstroResult) {
+      return {}
+    }
+    const diagnostics = context.parserServices.getAstroResult().diagnostics
+
+    return {
+      Program() {
+        for (const { text, code, location, severity } of diagnostics) {
+          if (severity === 2 /* Warning */) {
+            context.report({
+              loc: {
+                start: location,
+                end: location,
+              },
+              message: `${text} [${code}]`,
+            })
+          }
+        }
+      },
+    }
+  },
+})
diff --git a/src/types.ts b/src/types.ts
index c727492..6c24cb7 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -5,7 +5,7 @@ import type {
   Scope,
   SourceCode as ESLintSourceCode,
 } from "eslint"
-import type { AST } from "astro-eslint-parser"
+import type { AST, parseForESLint } from "astro-eslint-parser"
 import type * as ESTree from "estree"
 import type {
   ASTNode,
@@ -121,7 +121,7 @@ export type RuleContext = {
   }
   parserPath: string
   parserOptions: Linter.ParserOptions
-  parserServices: { isAstro?: boolean }
+  parserServices: Partial<ReturnType<typeof parseForESLint>["services"]>
 
   getAncestors(): ASTNode[]
 
diff --git a/src/utils/rules.ts b/src/utils/rules.ts
index 3a58755..fe83fef 100644
--- a/src/utils/rules.ts
+++ b/src/utils/rules.ts
@@ -11,6 +11,7 @@ import preferClassListDirective from "../rules/prefer-class-list-directive"
 import preferObjectClassList from "../rules/prefer-object-class-list"
 import preferSplitClassList from "../rules/prefer-split-class-list"
 import semi from "../rules/semi"
+import validCompile from "../rules/valid-compile"
 import { buildA11yRules } from "../a11y"
 
 export const rules = [
@@ -26,5 +27,6 @@ export const rules = [
   preferObjectClassList,
   preferSplitClassList,
   semi,
+  validCompile,
   ...buildA11yRules(),
 ] as RuleModule[]


Test patch:
diff --git a/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-errors.json b/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-errors.json
new file mode 100644
index 0000000..f694fa7
--- /dev/null
+++ b/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-errors.json
@@ -0,0 +1,12 @@
+[
+  {
+    "message": "set:html directive will overwrite child nodes. [2006]",
+    "line": 5,
+    "column": 5
+  },
+  {
+    "message": "set:html directive will overwrite child nodes. [2006]",
+    "line": 7,
+    "column": 5
+  }
+]
diff --git a/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-input.astro b/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-input.astro
new file mode 100644
index 0000000..343ef1d
--- /dev/null
+++ b/tests/fixtures/rules/valid-compile/invalid/child-with-set-html-input.astro
@@ -0,0 +1,17 @@
+---
+let string = "Foo"
+---
+
+<p set:html="string">string</p>
+<p set:html={string}>{string}</p>
+<p set:html={string}>string</p>
+<p set:html="string">{string}</p>
+<button set:html="string">
+  <div></div>
+</button>
+<button set:html="string">
+  <div>Foo</div>{string}
+</button>
+<p set:html="string">
+  <!-- comment -->{string}
+</p>
diff --git a/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-errors.json b/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-errors.json
new file mode 100644
index 0000000..838acac
--- /dev/null
+++ b/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-errors.json
@@ -0,0 +1,12 @@
+[
+  {
+    "message": "set:text directive will overwrite child nodes. [2006]",
+    "line": 5,
+    "column": 5
+  },
+  {
+    "message": "set:text directive will overwrite child nodes. [2006]",
+    "line": 7,
+    "column": 5
+  }
+]
diff --git a/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-input.astro b/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-input.astro
new file mode 100644
index 0000000..8b4c470
--- /dev/null
+++ b/tests/fixtures/rules/valid-compile/invalid/child-with-set-text-input.astro
@@ -0,0 +1,17 @@
+---
+let string = "Foo"
+---
+
+<p set:text="string">string</p>
+<p set:text={string}>{string}</p>
+<p set:text={string}>string</p>
+<p set:text="string">{string}</p>
+<button set:text="string">
+  <div></div>
+</button>
+<button set:text="string">
+  <div>Foo</div>{string}
+</button>
+<p set:text="string">
+  <!-- comment -->{string}
+</p>
diff --git a/tests/fixtures/rules/valid-compile/valid/child-input.astro b/tests/fixtures/rules/valid-compile/valid/child-input.astro
new file mode 100644
index 0000000..d172109
--- /dev/null
+++ b/tests/fixtures/rules/valid-compile/valid/child-input.astro
@@ -0,0 +1,11 @@
+---
+let string = "Foo"
+---
+
+<p></p>
+<p>string</p>
+<p>{string}</p>
+<p>
+  <!-- comment -->{string}
+</p>
+<div><p></p></div>
diff --git a/tests/src/rules/valid-compile.ts b/tests/src/rules/valid-compile.ts
new file mode 100644
index 0000000..e10dd0a
--- /dev/null
+++ b/tests/src/rules/valid-compile.ts
@@ -0,0 +1,12 @@
+import { RuleTester } from "eslint"
+import rule from "../../../src/rules/valid-compile"
+import { loadTestCases } from "../../utils/utils"
+
+const tester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 2020,
+    sourceType: "module",
+  },
+})
+
+tester.run("valid-compile", rule as any, loadTestCases("valid-compile"))