General fixes for odinfmt

This commit is contained in:
gingerBill
2021-05-21 10:21:23 +01:00
parent 362f07d7c5
commit 8758afdf4e
4 changed files with 76 additions and 105 deletions

View File

@@ -10,26 +10,25 @@ simplify :: proc(file: ^ast.File) {
}
format :: proc(source: [] u8, config: printer.Config, allocator := context.allocator) -> ([] u8, bool) {
format :: proc(source: string, config: printer.Config, parser_flags := parser.Flags{}, allocator := context.allocator) -> (string, bool) {
pkg := ast.Package {
kind = .Normal,
};
pkg := ast.Package {
kind = .Normal,
};
file := ast.File {
pkg = &pkg,
src = source,
};
file := ast.File {
pkg = &pkg,
src = source,
};
p := parser.default_parser(parser_flags);
p := parser.default_parser();
ok := parser.parse_file(&p, &file);
ok := parser.parse_file(&p, &file);
if !ok || file.syntax_error_count > 0 {
return {}, false;
}
if !ok || file.syntax_error_count > 0 {
return {}, false;
}
prnt := printer.make_printer(config, allocator);
prnt := printer.make_printer(config, allocator);
return transmute([]u8) printer.print(&prnt, &file), true;
}
return printer.print(&prnt, &file), true;
}

View File

@@ -8,7 +8,7 @@ import "core:fmt"
import "core:unicode/utf8"
import "core:mem"
Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit}
Type_Enum :: enum {Line_Comment, Value_Decl, Switch_Stmt, Struct, Assign, Call, Enum, If, For, Proc_Lit};
Line_Type :: bit_set[Type_Enum];
@@ -100,21 +100,21 @@ Newline_Style :: enum {
}
default_style := Config {
spaces = 4,
newline_limit = 2,
convert_do = false,
semicolons = true,
tabs = true,
brace_style = ._1TBS,
spaces = 4,
newline_limit = 2,
convert_do = false,
semicolons = true,
tabs = true,
brace_style = ._1TBS,
split_multiple_stmts = true,
align_assignments = true,
align_style = .Align_On_Type_And_Equals,
indent_cases = false,
align_switch = true,
align_structs = true,
align_enums = true,
newline_style = .CRLF,
align_length_break = 9,
align_assignments = true,
align_style = .Align_On_Type_And_Equals,
indent_cases = false,
align_switch = true,
align_structs = true,
align_enums = true,
newline_style = .CRLF,
align_length_break = 9,
};
make_printer :: proc(config: Config, allocator := context.allocator) -> Printer {
@@ -126,7 +126,6 @@ make_printer :: proc(config: Config, allocator := context.allocator) -> Printer
}
print :: proc(p: ^Printer, file: ^ast.File) -> string {
p.comments = file.comments;
if len(file.decls) > 0 {
@@ -387,7 +386,7 @@ format_keyword_to_brace :: proc(p: ^Printer, line_index: int, format_index: int,
break;
} else if format_token.kind == .Undef {
return;
}
}
if line_index == 0 && i <= format_index {
continue;
@@ -500,7 +499,7 @@ align_var_decls :: proc(p: ^Printer) {
line.format_tokens[i].kind == .Enum ||
line.format_tokens[i].kind == .Struct ||
line.format_tokens[i].kind == .For ||
line.format_tokens[i].kind == .If ||
line.format_tokens[i].kind == .If ||
line.format_tokens[i].kind == .Comment {
continue_flag = true;
}
@@ -583,7 +582,7 @@ align_var_decls :: proc(p: ^Printer) {
break;
}
}
}
//repeating myself, move to sub procedure
@@ -790,7 +789,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int {
length := 0;
for format_token, i in line.format_tokens {
//give up on nested structs
if format_token.kind == .Comment {
break;
@@ -825,7 +824,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int {
if colon_count >= brace_token.parameter_count {
break;
}
}
}
//give up aligning nested, it never looks good
if nested {
@@ -833,7 +832,7 @@ align_struct :: proc(p: ^Printer, index: int) -> int {
for format_token in line.format_tokens {
if format_token.kind == .Close_Brace {
return end_line_index + line_index - index;
}
}
}
}
}

View File

@@ -31,7 +31,6 @@ sort_attribute :: proc(s: ^[dynamic]^ast.Attribute) -> sort.Interface {
@(private)
comment_before_position :: proc(p: ^Printer, pos: tokenizer.Pos) -> bool {
if len(p.comments) <= p.latest_comment_index {
return false;
}
@@ -48,7 +47,6 @@ next_comment_group :: proc(p: ^Printer) {
@(private)
push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
if len(comment.text) == 0 {
return 0;
}
@@ -76,7 +74,6 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
return 0;
} else {
builder := strings.make_builder(context.temp_allocator);
c_len := len(comment.text);
@@ -156,12 +153,10 @@ push_comment :: proc(p: ^Printer, comment: tokenizer.Token) -> int {
@(private)
push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
prev_comment: ^tokenizer.Token;
prev_comment_lines: int;
for comment_before_position(p, pos) {
comment_group := p.comments[p.latest_comment_index];
if prev_comment == nil {
@@ -170,7 +165,6 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
}
for comment, i in comment_group.list {
if prev_comment != nil && p.last_source_position.line != comment.pos.line {
newline_position(p, min(p.config.newline_limit, comment.pos.line - prev_comment.pos.line - prev_comment_lines));
}
@@ -189,7 +183,6 @@ push_comments :: proc(p: ^Printer, pos: tokenizer.Pos) {
@(private)
append_format_token :: proc(p: ^Printer, format_token: Format_Token) -> ^Format_Token {
format_token := format_token;
if p.last_token != nil && (p.last_token.kind == .Ellipsis || p.last_token.kind == .Range_Half ||
@@ -231,7 +224,6 @@ push_format_token :: proc(p: ^Printer, format_token: Format_Token) {
@(private)
push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_before: int, value := "") {
format_token := Format_Token {
spaces_before = spaces_before,
kind = kind,
@@ -247,7 +239,6 @@ push_generic_token :: proc(p: ^Printer, kind: tokenizer.Token_Kind, spaces_befor
@(private)
push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) {
format_token := Format_Token {
spaces_before = spaces_before,
kind = .String,
@@ -259,7 +250,6 @@ push_string_token :: proc(p: ^Printer, text: string, spaces_before: int) {
@(private)
push_ident_token :: proc(p: ^Printer, text: string, spaces_before: int) {
format_token := Format_Token {
spaces_before = spaces_before,
kind = .Ident,
@@ -295,7 +285,6 @@ move_line_limit :: proc(p: ^Printer, pos: tokenizer.Pos, limit: int) -> bool {
@(private)
set_line :: proc(p: ^Printer, line: int) -> ^Line {
unwrapped_line: ^Line;
if line >= len(p.lines) {
@@ -348,7 +337,6 @@ hint_current_line :: proc(p: ^Printer, hint: Line_Type) {
@(private)
visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
using ast;
if decl == nil {
@@ -384,7 +372,6 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
push_ident_token(p, path, 0);
}
case Foreign_Block_Decl:
if len(v.attributes) > 0 {
sort.sort(sort_attribute(&v.attributes));
move_line(p, v.attributes[0].pos);
@@ -479,14 +466,13 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
@(private)
visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing := false, force_newline := false) {
if len(list) == 0 {
return;
}
//we have to newline the expressions to respect the source
// we have to newline the expressions to respect the source
for expr, i in list {
//Don't move the first expression, it looks bad
// Don't move the first expression, it looks bad
if i != 0 && force_newline {
newline_position(p, 1);
} else if i != 0 {
@@ -507,7 +493,6 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, add_comma := false, trailing
@(private)
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
if len(attributes) == 0 {
return;
}
@@ -526,7 +511,6 @@ visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
@(private)
visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Generic, empty_block := false, block_stmt := false) {
using ast;
if stmt == nil {
@@ -734,7 +718,7 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
push_generic_token(p, .Semicolon, 0);
}
case For_Stmt:
//this should be simplified
// this should be simplified
move_line(p, v.pos);
if v.label != nil {
@@ -796,7 +780,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
visit_expr(p, v.expr);
visit_stmt(p, v.body);
case Range_Stmt:
move_line(p, v.pos);
if v.label != nil {
@@ -864,7 +847,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
}
case Branch_Stmt:
move_line(p, v.pos);
push_generic_token(p, v.tok.kind, 0);
@@ -885,7 +867,6 @@ visit_stmt :: proc(p: ^Printer, stmt: ^ast.Stmt, block_type: Block_Type = .Gener
@(private)
visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
using ast;
if expr == nil {
@@ -1090,9 +1071,12 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
set_source_position(p, v.end);
case Proc_Lit:
if v.inlining == .Inline {
switch v.inlining {
case .None:
case .Inline:
push_ident_token(p, "#force_inline", 0);
case .No_Inline:
push_ident_token(p, "#force_no_inline", 0);
}
visit_proc_type(p, v.type^, true);
@@ -1121,11 +1105,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
case Call_Expr:
visit_expr(p, v.expr);
push_format_token(p, Format_Token {
kind = .Open_Paren,
type = .Call,
text = "(",
});
push_format_token(p,
Format_Token {
kind = .Open_Paren,
type = .Call,
text = "(",
},
);
hint_current_line(p, {.Call});
@@ -1152,7 +1138,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
visit_expr(p, v.index);
push_generic_token(p, .Close_Bracket, 0);
case Proc_Group:
push_generic_token(p, v.tok.kind, 1);
if len(v.args) != 0 && v.pos.line != v.args[len(v.args) - 1].pos.line {
@@ -1168,7 +1153,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
}
case Comp_Lit:
if v.type != nil {
visit_expr(p, v.type);
}
@@ -1244,7 +1228,6 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr) {
}
visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, count := 0) {
set_source_position(p, begin);
newline_braced := p.config.brace_style == .Allman;
@@ -1262,7 +1245,6 @@ visit_begin_brace :: proc(p: ^Printer, begin: tokenizer.Pos, type: Block_Type, c
push_format_token(p, format_token);
indent(p);
} else {
format_token.spaces_before = 1;
push_format_token(p, format_token);
indent(p);
}
@@ -1286,13 +1268,11 @@ visit_block_stmts :: proc(p: ^Printer, stmts: []^ast.Stmt, split := false) {
}
visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, add_comma := false, trailing := false, enforce_newline := false) {
if list.list == nil {
return;
}
for field, i in list.list {
if !move_line_limit(p, field.pos, 1) && enforce_newline {
newline_position(p, 1);
}
@@ -1325,7 +1305,6 @@ visit_field_list :: proc(p: ^Printer, list: ^ast.Field_List, add_comma := false,
}
visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := false) {
if is_proc_lit {
push_format_token(p, Format_Token {
kind = .Proc,
@@ -1357,11 +1336,8 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa
case .Fast_Call:
push_string_token(p, "\"fast\"", 1);
explicit_calling = true;
case .None:
//nothing i guess
case .Invalid:
//nothing i guess
case .Foreign_Block_Default:
case .None, .Invalid, .Foreign_Block_Default:
// nothing
}
if explicit_calling {
@@ -1405,7 +1381,6 @@ visit_proc_type :: proc(p: ^Printer, proc_type: ast.Proc_Type, is_proc_lit := fa
}
visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) {
move_line(p, binary.left.pos);
if v, ok := binary.left.derived.(ast.Binary_Expr); ok {
@@ -1430,15 +1405,13 @@ visit_binary_expr :: proc(p: ^Printer, binary: ast.Binary_Expr) {
}
visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
if len(list) == 0 {
return;
}
//all the expression are on the line
// all the expression are on the line
if list[0].pos.line == list[len(list) - 1].pos.line {
for expr, i in list {
if i == len(list) - 1 && ellipsis {
push_generic_token(p, .Ellipsis, 0);
}
@@ -1451,8 +1424,7 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
}
} else {
for expr, i in list {
//we have to newline the expressions to respect the source
// we have to newline the expressions to respect the source
move_line_limit(p, expr.pos, 1);
if i == len(list) - 1 && ellipsis {
@@ -1469,13 +1441,11 @@ visit_call_exprs :: proc(p: ^Printer, list: []^ast.Expr, ellipsis := false) {
}
visit_signature_list :: proc(p: ^Printer, list: ^ast.Field_List, remove_blank := true) {
if list.list == nil {
return;
}
for field, i in list.list {
if i != 0 {
move_line_limit(p, field.pos, 1);
}

View File

@@ -14,26 +14,31 @@ Args :: struct {
write: Maybe(bool) `flag:"w" usage:"write the new format to file"`,
}
print_help :: proc() {
print_help :: proc(args: []string) {
if len(args) == 0 {
fmt.eprint("odinfmt ");
} else {
fmt.eprintf("%s ", args[0]);
}
fmt.eprintln();
}
print_arg_error :: proc(error: flag.Flag_Error) {
fmt.println(error);
}
format_file :: proc(filepath: string) -> ([]u8, bool) {
format_file :: proc(filepath: string) -> (string, bool) {
if data, ok := os.read_entire_file(filepath); ok {
return format.format(data, format.default_style);
return format.format(string(data), format.default_style);
} else {
return {}, false;
return "", false;
}
}
files: [dynamic]string;
walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) {
if info.is_dir {
return 0, false;
}
@@ -48,13 +53,12 @@ walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip
}
main :: proc() {
init_global_temporary_allocator(mem.megabytes(100));
args: Args;
if len(os.args) < 2 {
print_help();
print_help(os.args);
os.exit(1);
}
@@ -69,13 +73,13 @@ main :: proc() {
if os.is_file(path) {
if _, ok := args.write.(bool); ok {
backup_path := strings.concatenate({path, "_bk"}, context.temp_allocator);
backup_path := strings.concatenate({path, "_bk"});
defer delete(backup_path);
if data, ok := format_file(path); ok {
os.rename(path, backup_path);
if os.write_entire_file(path, data) {
if os.write_entire_file(path, transmute([]byte)data) {
os.remove(backup_path);
}
} else {
@@ -83,7 +87,7 @@ main :: proc() {
}
} else {
if data, ok := format_file(path); ok {
fmt.println(transmute(string)data);
fmt.println(data);
}
}
} else if os.is_dir(path) {
@@ -92,24 +96,23 @@ main :: proc() {
for file in files {
fmt.println(file);
backup_path := strings.concatenate({file, "_bk"}, context.temp_allocator);
backup_path := strings.concatenate({file, "_bk"});
defer delete(backup_path);
if data, ok := format_file(file); ok {
if _, ok := args.write.(bool); ok {
os.rename(file, backup_path);
if os.write_entire_file(file, data) {
if os.write_entire_file(file, transmute([]byte)data) {
os.remove(backup_path);
}
} else {
fmt.println(transmute(string)data);
fmt.println(data);
}
} else {
fmt.eprintf("failed to format %v", file);
}
free_all(context.temp_allocator);
}
fmt.printf("formatted %v files in %vms", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time)));