aboutsummaryrefslogtreecommitdiff
path: root/src/server/action.odin
diff options
context:
space:
mode:
authorNathaniel Saxe <NathanielSaxophone@gmail.com>2026-02-03 17:03:16 -0500
committerNathaniel Saxe <NathanielSaxophone@gmail.com>2026-02-03 17:03:16 -0500
commite09faaa16c35721d37d61625ce14239ac29ba6eb (patch)
tree24762697988cd5a3dfabf9f668e64e16fc1b06e9 /src/server/action.odin
parent358a0d4df11731e18231da055813e7e6301ce4db (diff)
refactor into file; handle indentation
Diffstat (limited to 'src/server/action.odin')
-rw-r--r--src/server/action.odin182
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,
- },
- )
-}