From fa65e49bc689b2b84a3fa2dd123fa616f430f7fe Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Mon, 31 Aug 2020 20:53:42 +0900 Subject: [PATCH] feat(lint): Add support for reading input from stdin (#7263) --- cli/flags.rs | 4 ++ cli/lint.rs | 50 +++++++++++++++++++++ cli/tests/integration_tests.rs | 14 ++++++ cli/tests/lint/expected_from_stdin.out | 2 + cli/tests/lint/expected_from_stdin_json.out | 16 +++++++ docs/tools/linter.md | 6 +++ 6 files changed, 92 insertions(+) create mode 100644 cli/tests/lint/expected_from_stdin.out create mode 100644 cli/tests/lint/expected_from_stdin_json.out diff --git a/cli/flags.rs b/cli/flags.rs index 0bea5d72eb..3fcae5a818 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -1015,6 +1015,10 @@ fn lint_subcommand<'a, 'b>() -> App<'a, 'b> { Print result as JSON: deno lint --unstable --json +Read from stdin: + cat file.ts | deno lint --unstable - + cat file.ts | deno lint --unstable --json - + List available rules: deno lint --unstable --rules diff --git a/cli/lint.rs b/cli/lint.rs index 637e40b293..2edadecbf3 100644 --- a/cli/lint.rs +++ b/cli/lint.rs @@ -11,6 +11,7 @@ use crate::file_fetcher::map_file_extension; use crate::fmt::collect_files; use crate::fmt::run_parallelized; use crate::fmt_errors; +use crate::msg; use crate::swc_util; use deno_core::ErrBox; use deno_lint::diagnostic::LintDiagnostic; @@ -20,6 +21,7 @@ use deno_lint::rules; use deno_lint::rules::LintRule; use serde::Serialize; use std::fs; +use std::io::{stdin, Read}; use std::path::PathBuf; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; @@ -42,6 +44,9 @@ pub async fn lint_files( ignore: Vec, json: bool, ) -> Result<(), ErrBox> { + if args.len() == 1 && args[0] == "-" { + return lint_stdin(json); + } let mut target_files = collect_files(args)?; if !ignore.is_empty() { // collect all files to be ignored @@ -133,6 +138,51 @@ fn lint_file(file_path: PathBuf) -> Result, ErrBox> { Ok(file_diagnostics) } +/// Lint stdin and write result to stdout. +/// Treats input as TypeScript. +/// Compatible with `--json` flag. +fn lint_stdin(json: bool) -> Result<(), ErrBox> { + let mut source = String::new(); + if stdin().read_to_string(&mut source).is_err() { + return Err(ErrBox::error("Failed to read from stdin")); + } + + let reporter_kind = if json { + LintReporterKind::Json + } else { + LintReporterKind::Pretty + }; + let mut reporter = create_reporter(reporter_kind); + let lint_rules = rules::get_recommended_rules(); + let syntax = swc_util::get_syntax_for_media_type(msg::MediaType::TypeScript); + let mut linter = create_linter(syntax, lint_rules); + let mut has_error = false; + let pseudo_file_name = "_stdin.ts"; + match linter + .lint(pseudo_file_name.to_string(), source) + .map_err(|e| e.into()) + { + Ok(diagnostics) => { + for d in diagnostics { + has_error = true; + reporter.visit(&d); + } + } + Err(err) => { + has_error = true; + reporter.visit_error(pseudo_file_name, &err); + } + } + + reporter.close(); + + if has_error { + std::process::exit(1); + } + + Ok(()) +} + trait LintReporter { fn visit(&mut self, d: &LintDiagnostic); fn visit_error(&mut self, file_path: &str, err: &ErrBox); diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index c0dcdb606b..bf532e4045 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -2253,6 +2253,20 @@ itest!(deno_lint_glob { exit_code: 1, }); +itest!(deno_lint_from_stdin { + args: "lint --unstable -", + input: Some("let a: any;"), + output: "lint/expected_from_stdin.out", + exit_code: 1, +}); + +itest!(deno_lint_from_stdin_json { + args: "lint --unstable --json -", + input: Some("let a: any;"), + output: "lint/expected_from_stdin_json.out", + exit_code: 1, +}); + itest!(deno_doc_builtin { args: "doc", output: "deno_doc_builtin.out", diff --git a/cli/tests/lint/expected_from_stdin.out b/cli/tests/lint/expected_from_stdin.out new file mode 100644 index 0000000000..02b9d917c1 --- /dev/null +++ b/cli/tests/lint/expected_from_stdin.out @@ -0,0 +1,2 @@ +[WILDCARD] +Found 1 problem diff --git a/cli/tests/lint/expected_from_stdin_json.out b/cli/tests/lint/expected_from_stdin_json.out new file mode 100644 index 0000000000..bec5668410 --- /dev/null +++ b/cli/tests/lint/expected_from_stdin_json.out @@ -0,0 +1,16 @@ +{ + "diagnostics": [ + { + "location": { + "line": 1, + "col": 7 + }, + "filename": "_stdin.ts", + "message": "`any` type is not allowed", + "code": "no-explicit-any", + "line_src": "let a: any;", + "snippet_length": 3 + } + ], + "errors": [] +} diff --git a/docs/tools/linter.md b/docs/tools/linter.md index 22931a1c48..e2f1906b0f 100644 --- a/docs/tools/linter.md +++ b/docs/tools/linter.md @@ -10,8 +10,14 @@ flag** deno lint --unstable # lint specific files deno lint --unstable myfile1.ts myfile2.ts +# print result as JSON +deno lint --unstable --json +# read from stdin +cat file.ts | deno lint --unstable - ``` +For more detail, run `deno lint --help`. + ### Available rules - `adjacent-overload-signatures`