diff options
| author | Nathaniel Saxe <NathanielSaxophone@gmail.com> | 2026-02-03 17:03:16 -0500 |
|---|---|---|
| committer | Nathaniel Saxe <NathanielSaxophone@gmail.com> | 2026-02-03 17:03:16 -0500 |
| commit | e09faaa16c35721d37d61625ce14239ac29ba6eb (patch) | |
| tree | 24762697988cd5a3dfabf9f668e64e16fc1b06e9 /src/server/action.odin | |
| parent | 358a0d4df11731e18231da055813e7e6301ce4db (diff) | |
refactor into file; handle indentation
Diffstat (limited to 'src/server/action.odin')
| -rw-r--r-- | src/server/action.odin | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/src/server/action.odin b/src/server/action.odin index 43b38f3..64516a3 100644 --- a/src/server/action.odin +++ b/src/server/action.odin @@ -4,7 +4,6 @@ import "core:fmt" import "core:log" import "core:odin/ast" import path "core:path/slashpath" -import "core:slice" import "core:strings" import "src:common" @@ -194,184 +193,3 @@ add_missing_imports :: proc( return } - -@(private = "file") -get_block_original_text :: proc(block: []^ast.Stmt, document_text: []u8) -> string { - if len(block) == 0 { - return "" - } - start := block[0].pos - end := block[max(0, len(block) - 1)].end - return string(document_text[start.offset:end.offset]) -} - -@(private = "file") -get_switch_cases_info :: proc( - document: ^Document, - ast_context: ^AstContext, - position_context: ^DocumentPositionContext, -) -> ( - existing_cases: map[string]string, - existing_case_order: []string, - all_case_names: []string, - is_enum: bool, - ok: bool, -) { - if (position_context.switch_stmt == nil && position_context.switch_type_stmt == nil) || - (position_context.switch_stmt != nil && position_context.switch_stmt.cond == nil) { - return nil, nil, nil, false, false - } - switch_block: ^ast.Block_Stmt - found_switch_block: bool - if position_context.switch_stmt != nil { - switch_block, found_switch_block = position_context.switch_stmt.body.derived.(^ast.Block_Stmt) - is_enum = true - } - if !found_switch_block && position_context.switch_type_stmt != nil { - switch_block, found_switch_block = position_context.switch_type_stmt.body.derived.(^ast.Block_Stmt) - } - if !found_switch_block { - return nil, nil, nil, false, false - } - existing_cases = make(map[string]string, 5, context.temp_allocator) - existing_cases_in_order := make([dynamic]string, context.temp_allocator) - for stmt in switch_block.stmts { - if case_clause, ok := stmt.derived.(^ast.Case_Clause); ok { - case_name := "" - for name in case_clause.list { - if is_enum { - if implicit, ok := name.derived.(^ast.Implicit_Selector_Expr); ok { - case_name = implicit.field.name - break - } - } else { - reset_ast_context(ast_context) - if ty, ok := resolve_type_expression(ast_context, name); ok { - //TODO: this is wrong for anonymous enums and structs, where the name field is "enum" or "struct" respectively but we want to use the full signature - //we also can't use the signature all the time because type aliases need to use specifically the alias name here and not the signature - case_name = ty.name != "" ? ty.name : get_signature(ast_context, ty) - break - } - } - } - if case_name != "" { - existing_cases[case_name] = get_block_original_text(case_clause.body, document.text) - append(&existing_cases_in_order, case_name) - } - } - } - if is_enum { - enum_value, was_super_enum, unwrap_ok := unwrap_enum(ast_context, position_context.switch_stmt.cond) - if !unwrap_ok { - return nil, nil, nil, true, false - } - return existing_cases, existing_cases_in_order[:], enum_value.names, !was_super_enum, true - } else { - st := position_context.switch_type_stmt - if st == nil { - return nil, nil, nil, false, false - } - reset_ast_context(ast_context) - union_value, unwrap_ok := unwrap_union(ast_context, st.tag.derived.(^ast.Assign_Stmt).rhs[0]) - if !unwrap_ok { - return nil, nil, nil, false, false - } - case_names := make([]string, len(union_value.types), context.temp_allocator) - for t, i in union_value.types { - reset_ast_context(ast_context) - if ty, ok := resolve_type_expression(ast_context, t); ok { - //TODO: this is wrong for anonymous enums and structs, where the name field is "enum" or "struct" respectively but we want to use the full signature - //we also can't use the signature all the time because type aliases need to use specifically the alias name here and not the signature - case_names[i] = ty.name != "" ? ty.name : get_signature(ast_context, ty) - } else { - case_names[i] = "invalid type expression" - } - } - return existing_cases, existing_cases_in_order[:], case_names, false, true - } -} - -@(private = "file") -create_populate_switch_cases_edit :: proc( - position_context: ^DocumentPositionContext, - existing_cases: map[string]string, - existing_case_order: []string, - all_case_names: []string, - is_enum: bool, -) -> ( - TextEdit, - bool, -) { - //we need to be either in a switch stmt or a switch type stmt - if position_context.switch_stmt == nil && position_context.switch_type_stmt == nil { - return {}, false - } - //entirety of the switch block - range: common.Range - if is_enum { - range = common.get_token_range(position_context.switch_stmt.body.stmt_base, position_context.file.src) - } else { - range = common.get_token_range(position_context.switch_type_stmt.body.stmt_base, position_context.file.src) - } - replacement_builder := strings.builder_make() - dot := is_enum ? "." : "" - b := &replacement_builder - fmt.sbprintln(b, "{") - for name in existing_case_order { - fmt.sbprintln(b, "case ", dot, name, ":", sep = "") - case_block, case_exists := existing_cases[name] - if case_exists && case_block != "" { - fmt.sbprintln(b, existing_cases[name]) - } - } - for name in all_case_names { - if name in existing_cases {continue} //covered by prev loop - fmt.sbprintln(b, "case ", dot, name, ":", sep = "") - } - fmt.sbprint(b, "}") - return TextEdit{range = range, newText = strings.to_string(replacement_builder)}, true -} -add_populate_switch_cases_action :: proc( - document: ^Document, - ast_context: ^AstContext, - position_context: ^DocumentPositionContext, - uri: string, - actions: ^[dynamic]CodeAction, -) { - existing_cases, existing_case_order, all_case_names, is_enum, ok := get_switch_cases_info( - document, - ast_context, - position_context, - ) - if !ok {return} - all_cases_covered := true - for name in all_case_names { - if name not_in existing_cases { - all_cases_covered = false - } - } - if all_cases_covered {return} //action not needed - edit, edit_ok := create_populate_switch_cases_edit( - position_context, - existing_cases, - existing_case_order, - all_case_names, - is_enum, - ) - if !edit_ok {return} - textEdits := make([dynamic]TextEdit, context.temp_allocator) - append(&textEdits, 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 = "populate remaining switch cases", - edit = workspaceEdit, - }, - ) -} |