-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
477 additions
and
62 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
members = [ | ||
"ast", | ||
"cli", | ||
"fmt", | ||
"common", | ||
"compiler", | ||
"lexer", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[package] | ||
name = "whistle_fmt" | ||
version = "0.1.1" | ||
edition = "2021" | ||
|
||
[lib] | ||
crate-type = ["lib", "cdylib"] | ||
|
||
[dependencies] | ||
anyhow = "1.0.64" | ||
dprint-core = { version = "0.63.2", features = ["formatting"] } | ||
serde = { version = "1.0.144", features = ["derive"] } | ||
serde_json = { version = "1.0" } | ||
text_lines = "0.6.0" | ||
whistle_common = { path = "../common" } | ||
whistle_ast = { path = "../ast" } | ||
whistle_parser = { path = "../parser" } | ||
whistle_preprocessor = { path = "../preprocessor" } | ||
whistle_compiler = { path = "../compiler" } | ||
|
||
[dev-dependencies] | ||
debug-here = "0.2" | ||
dprint-development = "0.9.1" | ||
serde_json = { version = "1.0" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use dprint_core::configuration::NewLineKind; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Clone, Serialize, Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct Configuration { | ||
pub indent_width: u8, | ||
pub line_width: u32, | ||
pub use_tabs: bool, | ||
pub new_line_kind: NewLineKind, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use std::borrow::BorrowMut; | ||
|
||
use dprint_core::formatting::PrintItems; | ||
use whistle_ast::{IdentType, IdentTyped, ProgramStmt, Stmt}; | ||
|
||
use crate::{config::Configuration, ParsedSource}; | ||
|
||
pub fn generate(parsed_source: &ParsedSource, _config: &Configuration) -> PrintItems { | ||
let mut items = PrintItems::new(); | ||
let ast = &parsed_source.grammar; | ||
for item in ast { | ||
match item { | ||
ProgramStmt::FunctionDecl { | ||
export, | ||
inline, | ||
ident, | ||
params, | ||
ret_type, | ||
stmt, | ||
.. | ||
} => gen_fn( | ||
items.borrow_mut(), | ||
export, | ||
inline, | ||
ident, | ||
params, | ||
ret_type, | ||
stmt, | ||
), | ||
_ => panic!("Unimplemented"), | ||
}; | ||
} | ||
items | ||
} | ||
|
||
pub fn gen_fn( | ||
_items: &mut PrintItems, | ||
_export: &bool, | ||
_inline: &bool, | ||
_ident: &str, | ||
_params: &Vec<IdentTyped>, | ||
_ret_type: &IdentType, | ||
_stmts: &Vec<Stmt>, | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
#![feature(array_chunks)] | ||
Check failure on line 1 in fmt/src/lib.rs GitHub Actions / check
|
||
mod config; | ||
mod gen; | ||
mod utils; | ||
use anyhow::Result; | ||
use config::Configuration; | ||
use dprint_core::configuration::resolve_new_line_kind; | ||
use dprint_core::formatting::*; | ||
use gen::generate; | ||
use std::path::Path; | ||
use whistle_ast::Grammar; | ||
use whistle_parser::Parser; | ||
|
||
pub struct ParsedSource { | ||
pub parser: Parser, | ||
pub grammar: Grammar, | ||
pub text: String, | ||
} | ||
|
||
pub fn format_text( | ||
_file_path: &Path, | ||
file_text: &str, | ||
config: &Configuration, | ||
) -> Result<Option<String>> { | ||
if utils::file_text_has_ignore_comment(file_text, "// whistle-ignore-file") { | ||
Ok(None) | ||
} else { | ||
let parsed_source = utils::parse(file_text, false); | ||
let parsed_source = ParsedSource { | ||
parser: parsed_source.0, | ||
grammar: parsed_source.1, | ||
text: file_text.to_string(), | ||
}; | ||
inner_format(&parsed_source, config) | ||
} | ||
} | ||
|
||
/// Formats an already parsed source. This is useful as a performance optimization. | ||
pub fn format_parsed_source( | ||
source: ParsedSource, | ||
config: &Configuration, | ||
) -> Result<Option<String>> { | ||
if utils::file_text_has_ignore_comment(&source.text, "// whistle-ignore-file") { | ||
Ok(None) | ||
} else { | ||
// ensure_no_specific_syntax_errors(source)?; | ||
inner_format(&source, config) | ||
} | ||
} | ||
|
||
fn inner_format(parsed_source: &ParsedSource, config: &Configuration) -> Result<Option<String>> { | ||
let result = dprint_core::formatting::format( | ||
|| { | ||
#[allow(clippy::let_and_return)] | ||
let print_items = generate(parsed_source, config); | ||
println!("{}", print_items.get_as_text()); | ||
print_items | ||
}, | ||
config_to_print_options(parsed_source.text.as_str(), config), | ||
); | ||
if result == parsed_source.text.as_str() { | ||
Ok(None) | ||
} else { | ||
Ok(Some(result)) | ||
} | ||
} | ||
|
||
fn config_to_print_options(file_text: &str, config: &Configuration) -> PrintOptions { | ||
PrintOptions { | ||
indent_width: config.indent_width, | ||
max_width: config.line_width, | ||
use_tabs: config.use_tabs, | ||
new_line_text: resolve_new_line_kind(file_text, config.new_line_kind), | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use std::path::PathBuf; | ||
|
||
#[test] | ||
fn test_format_text() { | ||
let file_path = PathBuf::from("test.whistle"); | ||
let file_text = r#" | ||
// whistle-ignore-file | ||
export fn hi(): i32 { | ||
return 5 | ||
} | ||
"#; | ||
let config = Configuration { | ||
indent_width: 2, | ||
line_width: 80, | ||
use_tabs: false, | ||
new_line_kind: dprint_core::configuration::NewLineKind::LineFeed, | ||
}; | ||
let result = format_text(&file_path, file_text, &config).unwrap(); | ||
assert_eq!(result, None); | ||
} | ||
|
||
#[test] | ||
fn test_format_text2() { | ||
let file_path = PathBuf::from("test.whistle"); | ||
let file_text = r#" | ||
export fn hi(): i32 { | ||
return 5 | ||
} | ||
"#; | ||
let config = Configuration { | ||
indent_width: 2, | ||
line_width: 80, | ||
use_tabs: false, | ||
new_line_kind: dprint_core::configuration::NewLineKind::LineFeed, | ||
}; | ||
let result = format_text(&file_path, file_text, &config).unwrap(); | ||
assert_eq!( | ||
result, | ||
Some("export fn hi(): i32 {\n return 5\n}\n".to_string()) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
|
||
use whistle_ast::Grammar; | ||
use whistle_common::{DiagnosticHandler, TokenItem}; | ||
use whistle_parser::*; | ||
use whistle_preprocessor::Preprocessor; | ||
|
||
pub fn file_text_has_ignore_comment(file_text: &str, ignore_file_comment_text: &str) -> bool { | ||
let mut has_ignore_comment = false; | ||
for line in file_text.lines() { | ||
if line.trim().starts_with(ignore_file_comment_text) { | ||
has_ignore_comment = true; | ||
} | ||
} | ||
has_ignore_comment | ||
} | ||
|
||
pub fn preprocess(text: &str, print: bool) -> (Preprocessor, Vec<TokenItem>) { | ||
let handler = DiagnosticHandler::new(); | ||
let mut processor = Preprocessor::new(handler); | ||
processor.process(text); | ||
handle_errors(&mut processor.handler); | ||
let tokens = processor.finalize(); | ||
|
||
if print { | ||
println!("{:#?}", tokens); | ||
} | ||
|
||
(processor, tokens) | ||
} | ||
|
||
pub fn parse(text: &str, print: bool) -> (Parser, Grammar) { | ||
let (processor, tokens) = preprocess(text, false); | ||
let mut parser = Parser::new(processor, tokens); | ||
let grammar = parse_all(&mut parser); | ||
handle_errors(&mut parser.handler); | ||
|
||
if print { | ||
println!("{:#?}", grammar); | ||
} | ||
|
||
(parser, grammar) | ||
} | ||
|
||
pub fn handle_errors(handler: &mut DiagnosticHandler) { | ||
// TODO: format errors | ||
if handler.errors.len() > 0 { | ||
println!("{:#?}", handler.errors); | ||
}; | ||
} |