summaryrefslogtreecommitdiff
path: root/cli/fmt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/fmt.rs')
-rw-r--r--cli/fmt.rs162
1 files changed, 162 insertions, 0 deletions
diff --git a/cli/fmt.rs b/cli/fmt.rs
new file mode 100644
index 000000000..986be9fe1
--- /dev/null
+++ b/cli/fmt.rs
@@ -0,0 +1,162 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+//! This module provides file formating utilities using
+//! [`dprint`](https://github.com/dsherret/dprint).
+//!
+//! At the moment it is only consumed using CLI but in
+//! the future it can be easily extended to provide
+//! the same functions as ops available in JS runtime.
+
+use dprint_plugin_typescript::format_text;
+use dprint_plugin_typescript::Configuration;
+use dprint_plugin_typescript::ConfigurationBuilder;
+use glob;
+use regex::Regex;
+use std::fs;
+use std::path::Path;
+use std::path::PathBuf;
+use std::time::Instant;
+
+lazy_static! {
+ static ref TYPESCRIPT_LIB: Regex = Regex::new(".d.ts$").unwrap();
+ static ref TYPESCRIPT: Regex = Regex::new(".tsx?$").unwrap();
+ static ref JAVASCRIPT: Regex = Regex::new(".jsx?$").unwrap();
+}
+
+fn is_supported(path: &Path) -> bool {
+ let path_str = path.to_string_lossy();
+ !TYPESCRIPT_LIB.is_match(&path_str)
+ && (TYPESCRIPT.is_match(&path_str) || JAVASCRIPT.is_match(&path_str))
+}
+
+fn get_config() -> Configuration {
+ ConfigurationBuilder::new()
+ .line_width(80)
+ .indent_width(2)
+ .build()
+}
+
+fn get_supported_files(paths: Vec<PathBuf>) -> Vec<PathBuf> {
+ let mut files_to_check = vec![];
+
+ for path in paths {
+ if is_supported(&path) {
+ files_to_check.push(path.to_owned());
+ }
+ }
+
+ files_to_check
+}
+
+fn check_source_files(config: Configuration, paths: Vec<PathBuf>) {
+ let start = Instant::now();
+ let mut not_formatted_files = vec![];
+
+ for file_path in paths {
+ let file_path_str = file_path.to_string_lossy();
+ let file_contents = fs::read_to_string(&file_path).unwrap();
+ match format_text(&file_path_str, &file_contents, &config) {
+ Ok(None) => {
+ // nothing to format, pass
+ }
+ Ok(Some(formatted_text)) => {
+ if formatted_text != file_contents {
+ println!("Not formatted {}", file_path_str);
+ not_formatted_files.push(file_path);
+ }
+ }
+ Err(e) => {
+ eprintln!("Error checking: {}", &file_path_str);
+ eprintln!(" {}", e);
+ }
+ }
+ }
+
+ let duration = Instant::now() - start;
+
+ if !not_formatted_files.is_empty() {
+ let f = if not_formatted_files.len() == 1 {
+ "file"
+ } else {
+ "files"
+ };
+
+ eprintln!(
+ "Found {} not formatted {} in {:?}",
+ not_formatted_files.len(),
+ f,
+ duration
+ );
+ std::process::exit(1);
+ }
+}
+
+fn format_source_files(config: Configuration, paths: Vec<PathBuf>) {
+ let start = Instant::now();
+ let mut not_formatted_files = vec![];
+
+ for file_path in paths {
+ let file_path_str = file_path.to_string_lossy();
+ let file_contents = fs::read_to_string(&file_path).unwrap();
+ match format_text(&file_path_str, &file_contents, &config) {
+ Ok(None) => {
+ // nothing to format, pass
+ }
+ Ok(Some(formatted_text)) => {
+ if formatted_text != file_contents {
+ println!("Formatting {}", file_path_str);
+ fs::write(&file_path, formatted_text).unwrap();
+ not_formatted_files.push(file_path);
+ }
+ }
+ Err(e) => {
+ eprintln!("Error formatting: {}", &file_path_str);
+ eprintln!(" {}", e);
+ }
+ }
+ }
+
+ let duration = Instant::now() - start;
+ let f = if not_formatted_files.len() == 1 {
+ "file"
+ } else {
+ "files"
+ };
+ eprintln!(
+ "Formatted {} {} in {:?}",
+ not_formatted_files.len(),
+ f,
+ duration
+ );
+}
+
+fn get_matching_files(glob_paths: Vec<String>) -> Vec<PathBuf> {
+ let mut target_files = Vec::with_capacity(128);
+
+ for path in glob_paths {
+ let files = glob::glob(&path)
+ .expect("Failed to execute glob.")
+ .filter_map(Result::ok);
+ target_files.extend(files);
+ }
+
+ target_files
+}
+
+/// Format JavaScript/TypeScript files.
+///
+/// First argument supports globs, and if it is `None`
+/// then the current directory is recursively walked.
+pub fn format_files(maybe_files: Option<Vec<String>>, check: bool) {
+ // TODO: improve glob to look for tsx?/jsx? files only
+ let glob_paths = maybe_files.unwrap_or_else(|| vec!["**/*".to_string()]);
+ let matching_files = get_matching_files(glob_paths);
+ let matching_files = get_supported_files(matching_files);
+ let config = get_config();
+
+ if check {
+ check_source_files(config, matching_files);
+ } else {
+ format_source_files(config, matching_files);
+ }
+}