Skip to content

Commit

Permalink
feat(tasks): Add @typescript-eslint to lint_rules CI task (#2134)
Browse files Browse the repository at this point in the history
Part of #2020

- Add `@typescript-eslint` plugin rules
- w/ refactoring
  - Fix compile errors to add other plugins
  - Remove not intended unsupported rule in `eslint`

(Use #2117 for updating for a while?)
  • Loading branch information
leaysgur authored Jan 23, 2024
1 parent 0dc1804 commit 71173a9
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/lint-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ jobs:

- name: Update eslint
run: cargo run -p lint_rules eslint --update
- name: Update @typescript-eslint
run: cargo run -p lint_rules typescript --update
12 changes: 7 additions & 5 deletions tasks/lint_rules/src/generate_list/eslint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use std::collections::HashSet;

pub const ORIGINAL_JS_SOURCE_URL: &str =
const ORIGINAL_JS_SOURCE_URL: &str =
"https://raw.githubusercontent.com/eslint/eslint/main/packages/js/src/configs/eslint-all.js";

const UNSUPPORTED_RULES: &[&str] = &["yoda"];
const UNSUPPORTED_RULES: &[&str] = &[];

pub fn find_to_be_implemented_rules() -> Result<Vec<String>, String> {
let source_text = super::fetch_plugin_rules_js_string(ORIGINAL_JS_SOURCE_URL)?;

pub fn find_to_be_implemented_rules(source_text: &str) -> Result<Vec<String>, String> {
let allocator = Allocator::default();
let source_type = SourceType::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let ret = Parser::new(&allocator, &source_text, source_type).parse();

let program = allocator.alloc(ret.program);
let semantic_ret = SemanticBuilder::new(source_text, source_type).build(program);
let semantic_ret = SemanticBuilder::new(&source_text, source_type).build(program);

let mut rules = vec![];
let unsupported_rules = UNSUPPORTED_RULES.iter().collect::<HashSet<_>>();
Expand Down
13 changes: 6 additions & 7 deletions tasks/lint_rules/src/generate_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ use std::collections::HashSet;
use ureq::Response;

mod eslint;
mod typescript;

pub fn run(plugin_name: &str) -> Result<String, String> {
let (js_source_url, find_to_be_implemented_rules) = match plugin_name {
"eslint" => (eslint::ORIGINAL_JS_SOURCE_URL, eslint::find_to_be_implemented_rules),
let (rules_to_be_implemented, rules_implemented) = match plugin_name {
"eslint" => (eslint::find_to_be_implemented_rules()?, list_implemented_rules("eslint")),
"typescript" => {
(typescript::find_to_be_implemented_rules()?, list_implemented_rules("typescript"))
}
_ => return Err(format!("😢 Unknown plugin name: {plugin_name}")),
};

let js_string = fetch_plugin_rules_js_string(js_source_url)?;
let rules_to_be_implemented = find_to_be_implemented_rules(&js_string)?;

let rules_implemented = list_implemented_rules(plugin_name);

let list = render_markdown_todo_list(&rules_to_be_implemented, &rules_implemented);
let list = render_markdown_comment(plugin_name, &list);
Ok(list)
Expand Down
67 changes: 67 additions & 0 deletions tasks/lint_rules/src/generate_list/typescript.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use oxc_allocator::Allocator;
use oxc_ast::{ast::ObjectPropertyKind, syntax_directed_operations::PropName, AstKind};
use oxc_parser::Parser;
use oxc_semantic::SemanticBuilder;
use oxc_span::SourceType;
use std::collections::HashSet;

const ORIGINAL_JS_SOURCE_URL: &str =
"https://raw.githubusercontent.com/typescript-eslint/typescript-eslint/main/packages/eslint-plugin/src/configs/recommended.ts";

const UNSUPPORTED_RULES: &[&str] = &[];

pub fn find_to_be_implemented_rules() -> Result<Vec<String>, String> {
let source_text = super::fetch_plugin_rules_js_string(ORIGINAL_JS_SOURCE_URL)?;

let allocator = Allocator::default();
let source_type = SourceType::default().with_typescript(true);
let ret = Parser::new(&allocator, &source_text, source_type).parse();

let program = allocator.alloc(ret.program);
let semantic_ret = SemanticBuilder::new(&source_text, source_type).build(program);

let mut rules = vec![];
let unsupported_rules = UNSUPPORTED_RULES.iter().collect::<HashSet<_>>();

// This code assumes that the `rules` property appears only once
let mut is_rules = false;
for node in semantic_ret.semantic.nodes().iter() {
if let AstKind::ObjectProperty(prop) = node.kind() {
if let Some((name, _)) = prop.key.prop_name() {
if name == "rules" {
is_rules = true;
continue;
}
}
}

if is_rules {
if let AstKind::ObjectExpression(obj) = node.kind() {
for prop in &obj.properties {
if let ObjectPropertyKind::ObjectProperty(prop) = prop {
if let Some((name, _)) = prop.key.prop_name() {
// Almost all rules are prefixed, but some are not
// And prefixed and non-prefixed has the same name like `no-unused-vars`
if !name.starts_with("@typescript-eslint/") {
continue;
}

let name = name.trim_start_matches("@typescript-eslint/");
if unsupported_rules.contains(&name) {
continue;
}

rules.push(name.to_string());
}
}
}
}
}
}

if rules.is_empty() {
return Err("No rules are found".to_string());
}

Ok(rules)
}
5 changes: 4 additions & 1 deletion tasks/lint_rules/src/update_comment/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use ureq::Response;

const ESLINT_ISSUE_API_URL: &str = "https://api.github.com/repos/oxc-project/oxc/issues/2117";
// TODO: Restore it after update text is fixed and unsupported list is updated
const TYPESCRIPT_ISSUE_API_URL: &str = "https://api.github.com/repos/oxc-project/oxc/issues/2117";
// TODO: Restore these after update text is fixed and unsupported list is updated
// const ESLINT_ISSUE_API_URL: &str = "https://api.github.com/repos/oxc-project/oxc/issues/479";
// const TYPESCRIPT_ISSUE_API_URL: &str = "https://api.github.com/repos/oxc-project/oxc/issues/503";

pub fn run(plugin_name: &str, token: &str, comment_body: &str) -> Result<String, String> {
let api_url = match plugin_name {
"eslint" => ESLINT_ISSUE_API_URL,
"typescript" => TYPESCRIPT_ISSUE_API_URL,
_ => return Err(format!("😢 Unknown plugin name: {plugin_name}")),
};

Expand Down

0 comments on commit 71173a9

Please sign in to comment.