diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2023-08-28 20:32:05 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-28 20:32:05 +0200 |
| commit | 05ba253a873a70ca8d8c42eecaeebe4ac09e538a (patch) | |
| tree | 1da8b537f28ada2c347ddd120f9ef7b795f661a7 | |
| parent | a72ac2941a1a54e05b4051a00ca25b0b3822b1c6 (diff) | |
| parent | f4da51c35fef749ee609ba8673e8b4808c5f686b (diff) | |
Merge pull request #244 from laytan/sort-imports
sort imports
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | src/odin/printer/printer.odin | 62 |
2 files changed, 60 insertions, 4 deletions
@@ -104,6 +104,8 @@ Options: `tabs_width`: How many characters one tab represents +`sort_imports`: A boolean that defaults to true, which can be set to false to disable sorting imports. + ## Features Support Language server features: diff --git a/src/odin/printer/printer.odin b/src/odin/printer/printer.odin index d2af255..3e70159 100644 --- a/src/odin/printer/printer.odin +++ b/src/odin/printer/printer.odin @@ -1,10 +1,12 @@ package odin_printer +import "core:fmt" +import "core:log" +import "core:mem" import "core:odin/ast" import "core:odin/tokenizer" +import "core:slice" import "core:strings" -import "core:fmt" -import "core:mem" Printer :: struct { string_builder: strings.Builder, @@ -47,6 +49,7 @@ Config :: struct { brace_style: Brace_Style, indent_cases: bool, newline_style: Newline_Style, + sort_imports: bool, } Brace_Style :: enum { @@ -95,6 +98,7 @@ when ODIN_OS == .Windows { indent_cases = false, newline_style = .CRLF, character_width = 100, + sort_imports = true, } } else { default_style := Config { @@ -107,6 +111,7 @@ when ODIN_OS == .Windows { indent_cases = false, newline_style = .LF, character_width = 100, + sort_imports = true, } } @@ -222,8 +227,37 @@ print_file :: proc(p: ^Printer, file: ^ast.File) -> string { cons_with_nopl(text(file.pkg_token.text), text(file.pkg_name)), ) - for decl in file.decls { - p.document = cons(p.document, visit_decl(p, cast(^ast.Decl)decl)) + // Keep track of the first import in a row, to sort them later. + import_group_start: Maybe(int) + + for decl, i in file.decls { + decl := cast(^ast.Decl)decl + + if imp, is_import := decl.derived.(^ast.Import_Decl); + p.config.sort_imports && is_import { + // First import in this group. + if import_group_start == nil { + import_group_start = i + continue + } + + // If this import is on the next line, it is part of the group. + if imp.pos.line - 1 == file.decls[i - 1].end.line { + continue + } + + // This is an import, but it is separated, lets sort the current group. + print_sorted_imports(p, file.decls[import_group_start.?:i]) + import_group_start = i + } else { + // If there were imports before this declaration, sort and print them. + if import_group_start != nil { + print_sorted_imports(p, file.decls[import_group_start.?:i]) + import_group_start = nil + } + + p.document = cons(p.document, visit_decl(p, decl)) + } } if len(p.comments) > 0 { @@ -243,3 +277,23 @@ print_file :: proc(p: ^Printer, file: ^ast.File) -> string { return strings.to_string(p.string_builder) } + +// Sort the imports and add them to the document. +@(private) +print_sorted_imports :: proc(p: ^Printer, decls: []^ast.Stmt) { + start_line := decls[0].pos.line + + slice.stable_sort_by(decls, proc(imp1, imp2: ^ast.Stmt) -> bool { + return( + imp1.derived.(^ast.Import_Decl).fullpath < + imp2.derived.(^ast.Import_Decl).fullpath \ + ) + }) + + for decl, i in decls { + decl.pos.line = start_line + i + decl.end.line = start_line + i + + p.document = cons(p.document, visit_decl(p, cast(^ast.Decl)decl)) + } +} |