diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2021-03-12 16:31:09 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2021-03-12 16:31:09 +0100 |
| commit | 00ccd7e03e17dac40efb9b34a048d968dd77c218 (patch) | |
| tree | 24e9e8d9743bc3e98b63183d1f976b11ab6d93d2 /src/server/completion.odin | |
| parent | baf86e02a2c45170d58ab828a13f52361129b255 (diff) | |
ran odinfmt on project
Diffstat (limited to 'src/server/completion.odin')
| -rw-r--r-- | src/server/completion.odin | 1253 |
1 files changed, 575 insertions, 678 deletions
diff --git a/src/server/completion.odin b/src/server/completion.odin index 85c8c98..54c8b26 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -16,884 +16,781 @@ import "core:slice" import "shared:common" import "shared:index" -get_completion_list :: proc(document: ^Document, position: common.Position) -> (CompletionList, bool) { +get_completion_list :: proc (document: ^Document, position: common.Position) -> (CompletionList, bool) { - list: CompletionList; + list: CompletionList; - position_context, ok := get_document_position_context(document, position, .Completion); + position_context, ok := get_document_position_context(document, position, .Completion); - ast_context := make_ast_context(document.ast, document.imports, document.package_name); + ast_context := make_ast_context(document.ast, document.imports, document.package_name); - get_globals(document.ast, &ast_context); + get_globals(document.ast, &ast_context); - ast_context.current_package = ast_context.document_package; - ast_context.value_decl = position_context.value_decl; + ast_context.current_package = ast_context.document_package; + ast_context.value_decl = position_context.value_decl; - if position_context.function != nil { - get_locals(document.ast, position_context.function, &ast_context, &position_context); - } + if position_context.function != nil { + get_locals(document.ast, position_context.function, &ast_context, &position_context); + } - if position_context.implicit { - get_implicit_completion(&ast_context, &position_context, &list); - } + if position_context.implicit { + get_implicit_completion(&ast_context, &position_context, &list); + } else if position_context.switch_type_stmt != nil && position_context.case_clause != nil && position_context.identifier != nil { + get_type_switch_Completion(&ast_context, &position_context, &list); + } else if position_context.comp_lit != nil && is_lhs_comp_lit(&position_context) { + get_comp_lit_completion(&ast_context, &position_context, &list); + } else if position_context.selector != nil { + get_selector_completion(&ast_context, &position_context, &list); + } else if position_context.identifier != nil { + get_identifier_completion(&ast_context, &position_context, &list); + } - else if position_context.switch_type_stmt != nil && position_context.case_clause != nil && position_context.identifier != nil { - get_type_switch_Completion(&ast_context, &position_context, &list); - } - - else if position_context.comp_lit != nil && is_lhs_comp_lit(&position_context) { - get_comp_lit_completion(&ast_context, &position_context, &list); - } - - else if position_context.selector != nil { - get_selector_completion(&ast_context, &position_context, &list); - } - - else if position_context.identifier != nil { - get_identifier_completion(&ast_context, &position_context, &list); - } - - return list, true; + return list, true; } -is_lhs_comp_lit :: proc(position_context: ^DocumentPositionContext) -> bool { - - if len(position_context.comp_lit.elems) == 0 { - return true; - } - - for elem in position_context.comp_lit.elems { - - if position_in_node(elem, position_context.position) { +is_lhs_comp_lit :: proc (position_context: ^DocumentPositionContext) -> bool { - log.infof("in %v", elem.derived); + if len(position_context.comp_lit.elems) == 0 { + return true; + } - if ident, ok := elem.derived.(ast.Ident); ok { - return true; - } + for elem in position_context.comp_lit.elems { - else if field, ok := elem.derived.(ast.Field_Value); ok { + if position_in_node(elem, position_context.position) { - if position_in_node(field.value, position_context.position) { - return false; - } + log.infof("in %v", elem.derived); - } + if ident, ok := elem.derived.(ast.Ident); ok { + return true; + } else if field, ok := elem.derived.(ast.Field_Value); ok { - } + if position_in_node(field.value, position_context.position) { + return false; + } + } + } else { + log.infof("not in %v", elem.derived); + } + } - else { - log.infof("not in %v", elem.derived); - } - - } - - return true; + return true; } -field_exists_in_comp_lit :: proc(comp_lit: ^ast.Comp_Lit, name: string) -> bool { - - for elem in comp_lit.elems { - - if field, ok := elem.derived.(ast.Field_Value); ok { - - if field.field != nil { - - if ident, ok := field.field.derived.(ast.Ident); ok { +field_exists_in_comp_lit :: proc (comp_lit: ^ast.Comp_Lit, name: string) -> bool { - if ident.name == name { - return true; - } + for elem in comp_lit.elems { - } + if field, ok := elem.derived.(ast.Field_Value); ok { + if field.field != nil { - } + if ident, ok := field.field.derived.(ast.Ident); ok { - } + if ident.name == name { + return true; + } + } + } + } + } - } - - return false; + return false; } -get_directive_completion :: proc(ast_context: ^AstContext, postition_context: ^DocumentPositionContext, list: ^CompletionList) { - - list.isIncomplete = false; - - items := make([dynamic] CompletionItem, context.temp_allocator); - - /* - Right now just return all the possible completions, but later on I should give the context specific ones - */ - - directive_list := [] string { - "file", - "line", - "packed", - "raw_union", - "align", - "no_nil", - "complete", - "no_alias", - "caller_location", - "require_results", - "type", - "bounds_check", - "no_bounds_check", - "assert", - "defined", - "procedure", - "load", - "partial", - }; - - for elem in directive_list { - - item := CompletionItem { - detail = elem, - label = elem, - kind = .EnumMember, - }; - - append(&items, item); - - } - - +get_directive_completion :: proc (ast_context: ^AstContext, postition_context: ^DocumentPositionContext, list: ^CompletionList) { + + list.isIncomplete = false; + + items := make([dynamic]CompletionItem, context.temp_allocator); + + /* + Right now just return all the possible completions, but later on I should give the context specific ones + */ + + directive_list := []string { + "file", + "line", + "packed", + "raw_union", + "align", + "no_nil", + "complete", + "no_alias", + "caller_location", + "require_results", + "type", + "bounds_check", + "no_bounds_check", + "assert", + "defined", + "procedure", + "load", + "partial", + }; + + for elem in directive_list { + + item := CompletionItem { + detail = elem, + label = elem, + kind = .EnumMember, + }; + + append(&items, item); + } } -get_comp_lit_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - - items := make([dynamic] CompletionItem, context.temp_allocator); +get_comp_lit_completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - if position_context.parent_comp_lit.type == nil { - return; - } + items := make([dynamic]CompletionItem, context.temp_allocator); - if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { + if position_context.parent_comp_lit.type == nil { + return; + } - if comp_symbol, ok := resolve_type_comp_literal(ast_context, position_context, symbol, position_context.parent_comp_lit); ok { + if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { - #partial switch v in comp_symbol.value { - case index.SymbolStructValue: - for name, i in v.names { + if comp_symbol, ok := resolve_type_comp_literal(ast_context, position_context, symbol, position_context.parent_comp_lit); ok { - //ERROR no completion on name and hover - if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok { + #partial switch v in comp_symbol.value { + case index.SymbolStructValue: + for name, i in v.names { - if field_exists_in_comp_lit(position_context.comp_lit, name) { - continue; - } + //ERROR no completion on name and hover + if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok { - resolved.signature = index.node_to_string(v.types[i]); - resolved.pkg = comp_symbol.name; - resolved.name = name; - resolved.type = .Field; + if field_exists_in_comp_lit(position_context.comp_lit, name) { + continue; + } - item := CompletionItem { - label = resolved.name, - kind = cast(CompletionItemKind) resolved.type, - detail = concatenate_symbols_information(ast_context, resolved), - documentation = resolved.doc, - }; + resolved.signature = index.node_to_string(v.types[i]); + resolved.pkg = comp_symbol.name; + resolved.name = name; + resolved.type = .Field; - append(&items, item); - } - } - } - } - } + item := CompletionItem { + label = resolved.name, + kind = cast(CompletionItemKind)resolved.type, + detail = concatenate_symbols_information(ast_context, resolved), + documentation = resolved.doc, + }; + append(&items, item); + } + } + } + } + } - list.items = items[:]; + list.items = items[:]; } -get_selector_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { +get_selector_completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - items := make([dynamic] CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator); - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package; - if ident, ok := position_context.selector.derived.(ast.Ident); ok { + if ident, ok := position_context.selector.derived.(ast.Ident); ok { - if !resolve_ident_is_variable(ast_context, ident) && !resolve_ident_is_package(ast_context, ident) && ident.name != "" { - return; - } + if !resolve_ident_is_variable(ast_context, ident) && !resolve_ident_is_package(ast_context, ident) && ident.name != "" { + return; + } + } - } + symbols := make([dynamic]index.Symbol, context.temp_allocator); - symbols := make([dynamic] index.Symbol, context.temp_allocator); + selector: index.Symbol; + ok: bool; - selector: index.Symbol; - ok: bool; + ast_context.use_locals = true; + ast_context.use_globals = true; - ast_context.use_locals = true; - ast_context.use_globals = true; + selector, ok = resolve_type_expression(ast_context, position_context.selector); - selector, ok = resolve_type_expression(ast_context, position_context.selector); + if !ok { + return; + } - if !ok { - return; - } + if selector.pkg != "" { + ast_context.current_package = selector.pkg; + } else { + ast_context.current_package = ast_context.document_package; + } - if selector.pkg != "" { - ast_context.current_package = selector.pkg; - } + field: string; + + if position_context.field != nil { - else { - ast_context.current_package = ast_context.document_package; - } + switch v in position_context.field.derived { + case ast.Ident: + field = v.name; + } + } - field: string; + if s, ok := selector.value.(index.SymbolProcedureValue); ok { + if len(s.return_types) == 1 { + if selector, ok = resolve_type_expression(ast_context, s.return_types[0].type); !ok { + return; + } + } + } - if position_context.field != nil { + #partial switch v in selector.value { + case index.SymbolUnionValue: + list.isIncomplete = false; - switch v in position_context.field.derived { - case ast.Ident: - field = v.name; - } + for name in v.names { + symbol: index.Symbol; + symbol.name = fmt.aprintf("(%v)", name); + symbol.pkg = selector.name; + symbol.type = .EnumMember; + append(&symbols, symbol); + } - } + case index.SymbolEnumValue: + list.isIncomplete = false; + for name in v.names { + symbol: index.Symbol; + symbol.name = name; + symbol.pkg = selector.name; + symbol.type = .EnumMember; + append(&symbols, symbol); + } - if s, ok := selector.value.(index.SymbolProcedureValue); ok { - if len(s.return_types) == 1 { - if selector, ok = resolve_type_expression(ast_context, s.return_types[0].type); !ok { - return; - } - } - } + case index.SymbolStructValue: + list.isIncomplete = false; + for name, i in v.names { - #partial switch v in selector.value { - case index.SymbolUnionValue: - list.isIncomplete = false; + if selector.pkg != "" { + ast_context.current_package = selector.pkg; + } else { + ast_context.current_package = ast_context.document_package; + } - for name in v.names { - symbol: index.Symbol; - symbol.name = fmt.aprintf("(%v)", name); - symbol.pkg = selector.name; - symbol.type = .EnumMember; - append(&symbols, symbol); - } + if symbol, ok := resolve_type_expression(ast_context, v.types[i]); ok { - case index.SymbolEnumValue: - list.isIncomplete = false; + if expr, ok := position_context.selector.derived.(ast.Selector_Expr); ok { - for name in v.names { - symbol: index.Symbol; - symbol.name = name; - symbol.pkg = selector.name; - symbol.type = .EnumMember; - append(&symbols, symbol); - } + if expr.op.text == "->" && symbol.type != .Function { + continue; + } + } - case index.SymbolStructValue: - list.isIncomplete = false; + if position_context.arrow && symbol.type != .Function { + continue; + } - for name, i in v.names { - - if selector.pkg != "" { - ast_context.current_package = selector.pkg; - } - - else { - ast_context.current_package = ast_context.document_package; - } - - if symbol, ok := resolve_type_expression(ast_context, v.types[i]); ok { - - if expr, ok := position_context.selector.derived.(ast.Selector_Expr); ok { - - if expr.op.text == "->" && symbol.type != .Function { - continue; - } - - } - - if position_context.arrow && symbol.type != .Function { - continue; - } - - symbol.name = name; - symbol.type = .Field; - symbol.pkg = selector.name; - symbol.signature = index.node_to_string(v.types[i]); - append(&symbols, symbol); - } - - else { - //just give some generic symbol with name. - symbol: index.Symbol; - symbol.name = name; - symbol.type = .Field; - append(&symbols, symbol); - } - - } - - - case index.SymbolPackageValue: - - list.isIncomplete = true; - - if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok { - - for search in searched { - append(&symbols, search.symbol); - } - - } - - else { - log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg); - return; - } - - } - - for symbol, i in symbols { - - item := CompletionItem { - label = symbol.name, - kind = cast(CompletionItemKind) symbol.type, - detail = concatenate_symbols_information(ast_context, symbol), - documentation = symbol.doc, - }; - - append(&items, item); - } - - list.items = items[:]; + symbol.name = name; + symbol.type = .Field; + symbol.pkg = selector.name; + symbol.signature = index.node_to_string(v.types[i]); + append(&symbols, symbol); + } else { + //just give some generic symbol with name. + symbol: index.Symbol; + symbol.name = name; + symbol.type = .Field; + append(&symbols, symbol); + } + } + + case index.SymbolPackageValue: + + list.isIncomplete = true; + + if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok { + + for search in searched { + append(&symbols, search.symbol); + } + } else { + log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg); + return; + } + } + + for symbol, i in symbols { + + item := CompletionItem { + label = symbol.name, + kind = cast(CompletionItemKind)symbol.type, + detail = concatenate_symbols_information(ast_context, symbol), + documentation = symbol.doc, + }; + + append(&items, item); + } + + list.items = items[:]; } -unwrap_enum :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolEnumValue, bool) { - - if enum_symbol, ok := resolve_type_expression(ast_context, node); ok { +unwrap_enum :: proc (ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolEnumValue, bool) { - if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { - return enum_value, true; - } + if enum_symbol, ok := resolve_type_expression(ast_context, node); ok { - } + if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { + return enum_value, true; + } + } - return {}, false; + return {}, false; } -unwrap_union :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolUnionValue, bool) { - - if union_symbol, ok := resolve_type_expression(ast_context, node); ok { +unwrap_union :: proc (ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolUnionValue, bool) { - if union_value, ok := union_symbol.value.(index.SymbolUnionValue); ok { - return union_value, true; - } + if union_symbol, ok := resolve_type_expression(ast_context, node); ok { - } - - return {}, false; + if union_value, ok := union_symbol.value.(index.SymbolUnionValue); ok { + return union_value, true; + } + } + return {}, false; } -unwrap_bitset :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolEnumValue, bool) { - - if bitset_symbol, ok := resolve_type_expression(ast_context, node); ok { +unwrap_bitset :: proc (ast_context: ^AstContext, node: ^ast.Expr) -> (index.SymbolEnumValue, bool) { - if bitset_value, ok := bitset_symbol.value.(index.SymbolBitSetValue); ok { + if bitset_symbol, ok := resolve_type_expression(ast_context, node); ok { - if enum_symbol, ok := resolve_type_expression(ast_context, bitset_value.expr); ok { + if bitset_value, ok := bitset_symbol.value.(index.SymbolBitSetValue); ok { - if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { - return enum_value, true; - } - } + if enum_symbol, ok := resolve_type_expression(ast_context, bitset_value.expr); ok { - } + if enum_value, ok := enum_symbol.value.(index.SymbolEnumValue); ok { + return enum_value, true; + } + } + } + } - } - - return {}, false; + return {}, false; } -get_implicit_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - - items := make([dynamic] CompletionItem, context.temp_allocator); - - list.isIncomplete = false; - - selector: index.Symbol; - - ast_context.use_locals = true; - ast_context.use_globals = true; - - if selector.pkg != "" { - ast_context.current_package = selector.pkg; - } - - else { - ast_context.current_package = ast_context.document_package; - } - - //enum switch infer - if position_context.switch_stmt != nil && position_context.case_clause != nil && position_context.switch_stmt.cond != nil { - - used_enums := make(map [string]bool, 5, context.temp_allocator); - - if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok { - - for stmt in block.stmts { - - if case_clause, ok := stmt.derived.(ast.Case_Clause); ok { - - for name in case_clause.list { - - if implicit, ok := name.derived.(ast.Implicit_Selector_Expr); ok { - used_enums[implicit.field.name] = true; - } - } - } - } - } - - if enum_value, ok := unwrap_enum(ast_context, position_context.switch_stmt.cond); ok { - - for name in enum_value.names { - - if name in used_enums { - continue; - } - - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; - - append(&items, item); - - } - - } - - } - - else if position_context.comp_lit != nil && position_context.binary != nil && (position_context.binary.op.text == "&" ) { - //bitsets - context_node: ^ast.Expr; - bitset_node: ^ast.Expr; +get_implicit_completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - if position_in_node(position_context.binary.right, position_context.position) { - context_node = position_context.binary.right; - bitset_node = position_context.binary.left; - } + items := make([dynamic]CompletionItem, context.temp_allocator); - else if position_in_node(position_context.binary.left, position_context.position) { - context_node = position_context.binary.left; - bitset_node = position_context.binary.right; - } + list.isIncomplete = false; - if context_node != nil && bitset_node != nil { + selector: index.Symbol; - if _, ok := context_node.derived.(ast.Comp_Lit); ok { + ast_context.use_locals = true; + ast_context.use_globals = true; - if value, ok := unwrap_bitset(ast_context, bitset_node); ok { + if selector.pkg != "" { + ast_context.current_package = selector.pkg; + } else { + ast_context.current_package = ast_context.document_package; + } - for name in value.names { + //enum switch infer + if position_context.switch_stmt != nil && position_context.case_clause != nil && position_context.switch_stmt.cond != nil { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; + used_enums := make(map[string]bool, 5, context.temp_allocator); - append(&items, item); - } - } - } - } - } + if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok { - else if position_context.comp_lit != nil { + for stmt in block.stmts { - if position_context.parent_comp_lit.type == nil { - return; - } + if case_clause, ok := stmt.derived.(ast.Case_Clause); ok { - field_name: string; + for name in case_clause.list { - for elem in position_context.comp_lit.elems { + if implicit, ok := name.derived.(ast.Implicit_Selector_Expr); ok { + used_enums[implicit.field.name] = true; + } + } + } + } + } - if position_in_node(elem, position_context.position) { + if enum_value, ok := unwrap_enum(ast_context, position_context.switch_stmt.cond); ok { - if field, ok := elem.derived.(ast.Field_Value); ok { - field_name = field.field.derived.(ast.Ident).name; - } + for name in enum_value.names { - } + if name in used_enums { + continue; + } - } + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - if field_name == "" { - return; - } + append(&items, item); + } + } + } else if position_context.comp_lit != nil && position_context.binary != nil && (position_context.binary.op.text == "&") { + //bitsets + context_node: ^ast.Expr; + bitset_node: ^ast.Expr; - if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { + if position_in_node(position_context.binary.right, position_context.position) { + context_node = position_context.binary.right; + bitset_node = position_context.binary.left; + } else if position_in_node(position_context.binary.left, position_context.position) { + context_node = position_context.binary.left; + bitset_node = position_context.binary.right; + } - if comp_symbol, ok := resolve_type_comp_literal(ast_context, position_context, symbol, position_context.parent_comp_lit); ok { + if context_node != nil && bitset_node != nil { - if s, ok := comp_symbol.value.(index.SymbolStructValue); ok { + if _, ok := context_node.derived.(ast.Comp_Lit); ok { - for name, i in s.names { + if value, ok := unwrap_bitset(ast_context, bitset_node); ok { - if name != field_name { - continue; - } + for name in value.names { - if enum_value, ok := unwrap_enum(ast_context, s.types[i]); ok { - for enum_name in enum_value.names { - item := CompletionItem { - label = enum_name, - kind = .EnumMember, - detail = enum_name, - }; + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - append(&items, item); - } - } - } - } - } - } - } + append(&items, item); + } + } + } + } + } else if position_context.comp_lit != nil { - else if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") { + if position_context.parent_comp_lit.type == nil { + return; + } - context_node: ^ast.Expr; - enum_node: ^ast.Expr; + field_name: string; - if position_in_node(position_context.binary.right, position_context.position) { - context_node = position_context.binary.right; - enum_node = position_context.binary.left; - } + for elem in position_context.comp_lit.elems { - else if position_in_node(position_context.binary.left, position_context.position) { - context_node = position_context.binary.left; - enum_node = position_context.binary.right; - } + if position_in_node(elem, position_context.position) { - if context_node != nil && enum_node != nil { + if field, ok := elem.derived.(ast.Field_Value); ok { + field_name = field.field.derived.(ast.Ident).name; + } + } + } - if enum_value, ok := unwrap_enum(ast_context, enum_node); ok { + if field_name == "" { + return; + } - for name in enum_value.names { + if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; + if comp_symbol, ok := resolve_type_comp_literal(ast_context, position_context, symbol, position_context.parent_comp_lit); ok { - append(&items, item); - } - } - } - } + if s, ok := comp_symbol.value.(index.SymbolStructValue); ok { - else if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil { + for name, i in s.names { - rhs_index: int; + if name != field_name { + continue; + } - for elem in position_context.assign.rhs { + if enum_value, ok := unwrap_enum(ast_context, s.types[i]); ok { + for enum_name in enum_value.names { + item := CompletionItem { + label = enum_name, + kind = .EnumMember, + detail = enum_name, + }; - if position_in_node(elem, position_context.position) { - break; - } + append(&items, item); + } + } + } + } + } + } + } else if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") { - else { + context_node: ^ast.Expr; + enum_node: ^ast.Expr; - //procedures are the only types that can return more than one value - if symbol, ok := resolve_type_expression(ast_context, elem); ok { + if position_in_node(position_context.binary.right, position_context.position) { + context_node = position_context.binary.right; + enum_node = position_context.binary.left; + } else if position_in_node(position_context.binary.left, position_context.position) { + context_node = position_context.binary.left; + enum_node = position_context.binary.right; + } - if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok { + if context_node != nil && enum_node != nil { - if procedure.return_types == nil { - return; - } + if enum_value, ok := unwrap_enum(ast_context, enum_node); ok { - rhs_index += len(procedure.return_types); - } + for name in enum_value.names { - else { - rhs_index += 1; - } + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - } + append(&items, item); + } + } + } + } else if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil { - } + rhs_index: int; - } + for elem in position_context.assign.rhs { - if len(position_context.assign.lhs) > rhs_index { + if position_in_node(elem, position_context.position) { + break; + } else { - if enum_value, ok := unwrap_enum(ast_context, position_context.assign.lhs[rhs_index]); ok { + //procedures are the only types that can return more than one value + if symbol, ok := resolve_type_expression(ast_context, elem); ok { - for name in enum_value.names { + if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; + if procedure.return_types == nil { + return; + } - append(&items, item); + rhs_index += len(procedure.return_types); + } else { + rhs_index += 1; + } + } + } + } - } + if len(position_context.assign.lhs) > rhs_index { - } + if enum_value, ok := unwrap_enum(ast_context, position_context.assign.lhs[rhs_index]); ok { - } + for name in enum_value.names { - } + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - else if position_context.returns != nil && position_context.function != nil { + append(&items, item); + } + } + } + } else if position_context.returns != nil && position_context.function != nil { - return_index: int; + return_index: int; - if position_context.returns.results == nil { - return; - } + if position_context.returns.results == nil { + return; + } - for result, i in position_context.returns.results { + for result, i in position_context.returns.results { + + if position_in_node(result, position_context.position) { + return_index = i; + break; + } + } - if position_in_node(result, position_context.position) { - return_index = i; - break; - } + if position_context.function.type == nil { + return; + } - } + if position_context.function.type.results == nil { + return; + } - if position_context.function.type == nil { - return; - } + if len(position_context.function.type.results.list) > return_index { - if position_context.function.type.results == nil { - return; - } + if return_symbol, ok := resolve_type_expression(ast_context, position_context.function.type.results.list[return_index].type); ok { - if len(position_context.function.type.results.list) > return_index { + #partial switch v in return_symbol.value { + case index.SymbolEnumValue: + for name in v.names { - if return_symbol, ok := resolve_type_expression(ast_context, position_context.function.type.results.list[return_index].type); ok { + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - #partial switch v in return_symbol.value { - case index.SymbolEnumValue: - for name in v.names { + append(&items, item); + } + } + } + } + } - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; - - append(&items, item); - - } - - } - - } - - } - - - - - } - - - list.items = items[:]; + list.items = items[:]; } -get_identifier_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - - items := make([dynamic] CompletionItem, context.temp_allocator); +get_identifier_completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - list.isIncomplete = true; + items := make([dynamic]CompletionItem, context.temp_allocator); - CombinedResult :: struct { - score: f32, - symbol: index.Symbol, - variable: ^ast.Ident, - }; + list.isIncomplete = true; - combined_sort_interface :: proc(s: ^[dynamic] CombinedResult) -> sort.Interface { - return sort.Interface{ - collection = rawptr(s), - len = proc(it: sort.Interface) -> int { - s := (^[dynamic] CombinedResult)(it.collection); - return len(s^); - }, - less = proc(it: sort.Interface, i, j: int) -> bool { - s := (^[dynamic] CombinedResult)(it.collection); - return s[i].score > s[j].score; - }, - swap = proc(it: sort.Interface, i, j: int) { - s := (^[dynamic] CombinedResult)(it.collection); - s[i], s[j] = s[j], s[i]; - }, - }; - } + CombinedResult :: struct { + score: f32, + symbol: index.Symbol, + variable: ^ast.Ident, + }; - combined := make([dynamic] CombinedResult); + combined_sort_interface :: proc (s: ^[dynamic]CombinedResult) -> sort.Interface { + return sort.Interface { + collection = rawptr(s), + len = proc (it: sort.Interface) -> int { + s := (^[dynamic]CombinedResult)(it.collection); + return len(s^); + }, + less = proc (it: sort.Interface, i, j: int) -> bool { + s := (^[dynamic]CombinedResult)(it.collection); + return s[i].score > s[j].score; + }, + swap = proc (it: sort.Interface, i, j: int) { + s := (^[dynamic]CombinedResult)(it.collection); + s[i], s[j] = s[j], s[i]; + }, + }; + }; - lookup := ""; + combined := make([dynamic]CombinedResult); - if ident, ok := position_context.identifier.derived.(ast.Ident); ok { - lookup = ident.name; - } + lookup := ""; - pkgs := make([dynamic] string, context.temp_allocator); + if ident, ok := position_context.identifier.derived.(ast.Ident); ok { + lookup = ident.name; + } - usings := get_using_packages(ast_context); + pkgs := make([dynamic]string, context.temp_allocator); - for u in usings { - append(&pkgs, u); - } + usings := get_using_packages(ast_context); - append(&pkgs, ast_context.document_package); + for u in usings { + append(&pkgs, u); + } - if results, ok := index.fuzzy_search(lookup, pkgs[:]); ok { + append(&pkgs, ast_context.document_package); - for r in results { - append(&combined, CombinedResult { score = r.score, symbol = r.symbol}); - } + if results, ok := index.fuzzy_search(lookup, pkgs[:]); ok { - } + for r in results { + append(&combined, CombinedResult {score = r.score, symbol = r.symbol}); + } + } - matcher := common.make_fuzzy_matcher(lookup); + matcher := common.make_fuzzy_matcher(lookup); - global: for k, v in ast_context.globals { + global: for k, v in ast_context.globals { - //combined is sorted and should do binary search instead. - for result in combined { - if result.symbol.name == k { - continue global; - } - } + //combined is sorted and should do binary search instead. + for result in combined { + if result.symbol.name == k { + continue global; + } + } - ast_context.use_locals = true; - ast_context.use_globals = true; - ast_context.current_package = ast_context.document_package; + ast_context.use_locals = true; + ast_context.use_globals = true; + ast_context.current_package = ast_context.document_package; - ident := index.new_type(ast.Ident, v.pos, v.end, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, v.pos, v.end, context.temp_allocator); + ident.name = k; - if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.name = ident.name; - symbol.signature = get_signature(ast_context, ident^, symbol); + if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { + symbol.name = ident.name; + symbol.signature = get_signature(ast_context, ident^, symbol); - if score, ok := common.fuzzy_match(matcher, symbol.name); ok { - append(&combined, CombinedResult { score = score * 1.1, symbol = symbol, variable = ident }); - } + if score, ok := common.fuzzy_match(matcher, symbol.name); ok { + append(&combined, CombinedResult {score = score * 1.1, symbol = symbol, variable = ident}); + } + } + } - } - } + for k, v in ast_context.locals { + ast_context.use_locals = true; + ast_context.use_globals = true; + ast_context.current_package = ast_context.document_package; + ident := index.new_type(ast.Ident, {offset = position_context.position}, {offset = position_context.position}, context.temp_allocator); + ident.name = k; - for k, v in ast_context.locals { + if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { + symbol.name = ident.name; + symbol.signature = get_signature(ast_context, ident^, symbol); - ast_context.use_locals = true; - ast_context.use_globals = true; - ast_context.current_package = ast_context.document_package; + if score, ok := common.fuzzy_match(matcher, symbol.name); ok { + append(&combined, CombinedResult {score = score * 1.1, symbol = symbol, variable = ident}); + } + } + } + for pkg in ast_context.imports { - ident := index.new_type(ast.Ident, { offset = position_context.position }, { offset = position_context.position }, context.temp_allocator); - ident.name = k; + symbol: index.Symbol; - if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.name = ident.name; - symbol.signature = get_signature(ast_context, ident^, symbol); + symbol.name = pkg.base; + symbol.type = .Package; - if score, ok := common.fuzzy_match(matcher, symbol.name); ok { - append(&combined, CombinedResult { score = score * 1.1, symbol = symbol, variable = ident }); - } + if score, ok := common.fuzzy_match(matcher, symbol.name); ok { + append(&combined, CombinedResult {score = score * 1.1, symbol = symbol}); + } + } - } - } + sort.sort(combined_sort_interface(&combined)); - for pkg in ast_context.imports { + //hard code for now + top_results := combined[0:(min(20, len(combined)))]; - symbol: index.Symbol; + for result in top_results { - symbol.name = pkg.base; - symbol.type = .Package; + item := CompletionItem { + label = result.symbol.name, + detail = concatenate_symbols_information(ast_context, result.symbol), + }; - if score, ok := common.fuzzy_match(matcher, symbol.name); ok { - append(&combined, CombinedResult { score = score * 1.1, symbol = symbol }); - } - } + if result.variable != nil { + if ok := resolve_ident_is_variable(ast_context, result.variable^); ok { + item.kind = .Variable; + } else { + item.kind = cast(CompletionItemKind)result.symbol.type; + } + } else { + item.kind = cast(CompletionItemKind)result.symbol.type; + } - sort.sort(combined_sort_interface(&combined)); + append(&items, item); + } - //hard code for now - top_results := combined[0:(min(20, len(combined)))]; - - for result in top_results { - - item := CompletionItem { - label = result.symbol.name, - detail = concatenate_symbols_information(ast_context, result.symbol), - }; - - if result.variable != nil { - if ok := resolve_ident_is_variable(ast_context, result.variable^); ok { - item.kind = .Variable; - } - - else { - item.kind = cast(CompletionItemKind)result.symbol.type; - } - } - - else { - item.kind = cast(CompletionItemKind)result.symbol.type; - } - - append(&items, item); - } - - list.items = items[:]; + list.items = items[:]; } -get_package_completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - - - - +get_package_completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { } -get_type_switch_Completion :: proc(ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - +get_type_switch_Completion :: proc (ast_context: ^AstContext, position_context: ^DocumentPositionContext, list: ^CompletionList) { - items := make([dynamic] CompletionItem, context.temp_allocator); - list.isIncomplete = false; + items := make([dynamic]CompletionItem, context.temp_allocator); + list.isIncomplete = false; - if assign, ok := position_context.switch_type_stmt.tag.derived.(ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { + if assign, ok := position_context.switch_type_stmt.tag.derived.(ast.Assign_Stmt); ok && assign.rhs != nil && len(assign.rhs) == 1 { - if union_value, ok := unwrap_union(ast_context, assign.rhs[0]); ok { + if union_value, ok := unwrap_union(ast_context, assign.rhs[0]); ok { - for name in union_value.names { + for name in union_value.names { - item := CompletionItem { - label = name, - kind = .EnumMember, - detail = name, - }; + item := CompletionItem { + label = name, + kind = .EnumMember, + detail = name, + }; - append(&items, item); - } - } - } + append(&items, item); + } + } + } - list.items = items[:]; + list.items = items[:]; }
\ No newline at end of file |