diff options
| -rw-r--r-- | src/server/action.odin | 42 | ||||
| -rw-r--r-- | src/server/documents.odin | 3 | ||||
| -rw-r--r-- | src/server/format.odin | 4 | ||||
| -rw-r--r-- | src/server/imports.odin | 30 |
4 files changed, 69 insertions, 10 deletions
diff --git a/src/server/action.odin b/src/server/action.odin index 0c3c74a..0c522bf 100644 --- a/src/server/action.odin +++ b/src/server/action.odin @@ -67,11 +67,53 @@ get_code_actions :: proc(document: ^Document, range: common.Range, config: ^comm if selector, ok := position_context.selector_expr.derived.(^ast.Selector_Expr); ok { add_missing_imports(&ast_context, selector, strings.clone(document.uri.uri), config, &actions) } + } else if position_context.import_stmt != nil { + remove_missing_imports(document, strings.clone(document.uri.uri), config, &actions) } return actions[:], true } +remove_missing_imports :: proc( + document: ^Document, + uri: string, + config: ^common.Config, + actions: ^[dynamic]CodeAction, +) { + unused_imports := find_unused_imports(document, context.temp_allocator) + + if len(unused_imports) == 0 { + return + } + + textEdits := make([dynamic]TextEdit, context.temp_allocator) + + for imp in unused_imports { + range := common.get_token_range(imp.import_decl, document.ast.src) + import_edit := TextEdit { + range = range, + newText = "", + } + + append(&textEdits, import_edit) + } + + workspaceEdit: WorkspaceEdit + workspaceEdit.changes = make(map[string][]TextEdit, 0, context.temp_allocator) + workspaceEdit.changes[uri] = textEdits[:] + + append( + actions, + CodeAction { + kind = "refactor.rewrite", + isPreferred = true, + title = fmt.tprint("remove unused imports"), + edit = workspaceEdit, + }, + ) + +} + add_missing_imports :: proc( ast_context: ^AstContext, selector: ^ast.Selector_Expr, diff --git a/src/server/documents.odin b/src/server/documents.odin index dee90d5..cf8a344 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -29,6 +29,7 @@ Package :: struct { base: string, base_original: string, original: string, + import_decl: ^ast.Import_Decl, } Document :: struct { @@ -446,6 +447,7 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { import_: Package import_.original = imp.fullpath import_.name = strings.clone(path.join(elems = {dir, p}, allocator = context.temp_allocator)) + import_.import_decl = imp if imp.name.text != "" { import_.base = imp.name.text @@ -468,6 +470,7 @@ parse_imports :: proc(document: ^Document, config: ^common.Config) { allocator = context.temp_allocator, ) import_.name = path.clean(import_.name) + import_.import_decl = imp if imp.name.text != "" { import_.base = imp.name.text diff --git a/src/server/format.odin b/src/server/format.odin index d981b9c..9f30c49 100644 --- a/src/server/format.odin +++ b/src/server/format.odin @@ -29,10 +29,6 @@ get_complete_format :: proc(document: ^Document, config: ^common.Config) -> ([]T return {}, true } - if config.enable_import_fixer { - fix_imports(document) - } - style := format.find_config_file_or_default(filepath.dir(document.fullpath, context.temp_allocator)) prnt := printer.make_printer(style, context.temp_allocator) diff --git a/src/server/imports.odin b/src/server/imports.odin index cd2271d..4da5a86 100644 --- a/src/server/imports.odin +++ b/src/server/imports.odin @@ -1,17 +1,35 @@ package server +import "core:log" import "core:mem" import "core:odin/ast" +import "base:runtime" -fix_imports :: proc(document: ^Document) { - arena: mem.Arena - mem.arena_init(&arena, make([]byte, mem.Megabyte * 25)) - defer delete(arena.data) +find_unused_imports :: proc(document: ^Document, allocator := context.temp_allocator) -> []Package { + arena: runtime.Arena - context.allocator = mem.arena_allocator(&arena) + _ = runtime.arena_init(&arena, mem.Megabyte * 40, runtime.default_allocator()) - symbols_and_nodes := resolve_entire_file(document, .None) + defer runtime.arena_destroy(&arena) + context.allocator = runtime.arena_allocator(&arena) + symbols_and_nodes := resolve_entire_file_cached(document) + + pkgs := make(map[string]bool, context.temp_allocator) + + for _, v in symbols_and_nodes { + pkgs[v.symbol.pkg] = true + } + + unused := make([dynamic]Package, allocator) + + for imp in document.imports { + if imp.name not_in pkgs { + append(&unused, imp) + } + } + + return unused[:] } |