diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-03-04 12:17:00 +0100 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-03-04 12:17:00 +0100 |
| commit | 58287455d64ab16091522bf8a358b079ef05daad (patch) | |
| tree | 7b6655d6d34b5ad6d719523e4938b8002c43d8ab /src/server/completion.odin | |
| parent | 63d0bd412a8817445d6dc18e79d5d54c94caf401 (diff) | |
strip colons and update ast to use unions
Diffstat (limited to 'src/server/completion.odin')
| -rw-r--r-- | src/server/completion.odin | 652 |
1 files changed, 328 insertions, 324 deletions
diff --git a/src/server/completion.odin b/src/server/completion.odin index 59df7a3..ae9d4e3 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -35,64 +35,64 @@ Completion_Type :: enum { } get_completion_list :: proc(document: ^common.Document, position: common.Position, completion_context: CompletionContext) -> (CompletionList, bool) { - using analysis; + using analysis - list: CompletionList; + list: CompletionList - position_context, ok := get_document_position_context(document, position, .Completion); + position_context, ok := get_document_position_context(document, position, .Completion) if !ok || position_context.abort_completion { - return list, true; + return list, true } if position_context.import_stmt == nil && strings.contains_any(completion_context.triggerCharacter, "/:\"") { - return list, true; + return list, true } - ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri); + ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri) - 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); + get_locals(document.ast, position_context.function, &ast_context, &position_context) } - completion_type: Completion_Type = .Identifier; + completion_type: Completion_Type = .Identifier if position_context.comp_lit != nil && is_lhs_comp_lit(&position_context) { - completion_type = .Comp_Lit; + completion_type = .Comp_Lit } if position_context.selector != nil { - completion_type = .Selector; + completion_type = .Selector } if position_context.tag != nil { - completion_type = .Directive; + completion_type = .Directive } if position_context.implicit { - completion_type = .Implicit; + completion_type = .Implicit } if position_context.import_stmt != nil { - completion_type = .Package; + completion_type = .Package } if position_context.switch_type_stmt != nil && position_context.case_clause != nil { - 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 { - ast_context.use_globals = true; - ast_context.use_locals = true; + ast_context.use_globals = true + ast_context.use_locals = true if symbol, ok := resolve_type_expression(&ast_context, assign.rhs[0]); ok { if union_value, ok := symbol.value.(index.SymbolUnionValue); ok { - completion_type = .Switch_Type; + completion_type = .Switch_Type } } } @@ -100,22 +100,22 @@ get_completion_list :: proc(document: ^common.Document, position: common.Positio switch completion_type { case .Comp_Lit: - get_comp_lit_completion(&ast_context, &position_context, &list); + get_comp_lit_completion(&ast_context, &position_context, &list) case .Identifier: - get_identifier_completion(&ast_context, &position_context, &list); + get_identifier_completion(&ast_context, &position_context, &list) case .Implicit: - get_implicit_completion(&ast_context, &position_context, &list); + get_implicit_completion(&ast_context, &position_context, &list) case .Selector: - get_selector_completion(&ast_context, &position_context, &list); + get_selector_completion(&ast_context, &position_context, &list) case .Switch_Type: - get_type_switch_completion(&ast_context, &position_context, &list); + get_type_switch_completion(&ast_context, &position_context, &list) case .Directive: - get_directive_completion(&ast_context, &position_context, &list); + get_directive_completion(&ast_context, &position_context, &list) case .Package: - get_package_completion(&ast_context, &position_context, &list); + get_package_completion(&ast_context, &position_context, &list) } - return list, true; + return list, true } get_attribute_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { @@ -124,9 +124,9 @@ get_attribute_completion :: proc(ast_context: ^analysis.AstContext, position_con get_directive_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - list.isIncomplete = false; + list.isIncomplete = false - items := make([dynamic]CompletionItem, context.temp_allocator); + 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 @@ -151,28 +151,28 @@ get_directive_completion :: proc(ast_context: ^analysis.AstContext, position_con "procedure", "load", "partial", - }; + } for elem in directive_list { item := CompletionItem { detail = elem, label = elem, kind = .Constant, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; + list.items = items[:] } get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) if position_context.parent_comp_lit.type == nil { - return; + return } if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { @@ -180,11 +180,11 @@ get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_cont #partial switch v in comp_symbol.value { case index.SymbolStructValue: for name, i in v.names { - ast_context.current_package = comp_symbol.pkg; + ast_context.current_package = comp_symbol.pkg if resolved, ok := resolve_type_expression(ast_context, v.types[i]); ok { if field_exists_in_comp_lit(position_context.comp_lit, name) { - continue; + continue } item := CompletionItem { @@ -192,126 +192,126 @@ get_comp_lit_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v.%v: %v", comp_symbol.name, name, common.node_to_string(v.types[i])), documentation = resolved.doc, - }; + } - append(&items, item); + append(&items, item) } } } } } - list.items = items[:]; + list.items = items[:] } get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - 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 - 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; + return } //if (selector.type != .Variable && selector.type != .Package && selector.type != .Enum && selector.name != "") || (selector.type == .Variable && selector.type == .Enum) { if selector.type != .Variable && selector.type != .Package { - return; + return } if selector.pkg != "" { - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg } else { - ast_context.current_package = ast_context.document_package; + ast_context.current_package = ast_context.document_package } - field: string; + field: string if position_context.field != nil { - switch v in position_context.field.derived { - case ast.Ident: - field = v.name; + #partial switch v in position_context.field.derived { + case ^ast.Ident: + field = v.name } } 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; + return } } } #partial switch v in selector.value { case index.SymbolFixedArrayValue: - list.isIncomplete = true; + list.isIncomplete = true - containsColor := 1; - containsCoord := 1; + containsColor := 1 + containsCoord := 1 - expr_len := 0; + expr_len := 0 - if basic, ok := v.len.derived.(ast.Basic_Lit); ok { + if basic, ok := v.len.derived.(^ast.Basic_Lit); ok { if expr_len, ok = strconv.parse_int(basic.tok.text); !ok { - expr_len = 0; + expr_len = 0 } } if field != "" { for i := 0; i < len(field); i += 1 { - c := field[i]; + c := field[i] if _, ok := swizzle_color_components[c]; ok { - containsColor += 1; + containsColor += 1 } else if _, ok := swizzle_coord_components[c]; ok { - containsCoord += 1; + containsCoord += 1 } } } if containsColor == 1 && containsCoord == 1 { - save := expr_len; + save := expr_len for k in swizzle_color_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: %v", field, k, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } - expr_len = save; + expr_len = save for k in swizzle_coord_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: %v", field, k, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } @@ -319,90 +319,90 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont for k in swizzle_color_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: [%v]%v", field, k, containsColor, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } else if containsCoord > 1 { for k in swizzle_coord_components { if expr_len <= 0 { - break; + break } - expr_len -= 1; + expr_len -= 1 item := CompletionItem { label = fmt.tprintf("%v%c", field, k), kind = .Property, detail = fmt.tprintf("%v%c: [%v]%v", field, k, containsCoord, common.node_to_string(v.expr)), - }; - append(&items, item); + } + append(&items, item) } } case index.SymbolUnionValue: - list.isIncomplete = false; + list.isIncomplete = false for type in v.types { if symbol, ok := resolve_type_expression(ast_context, type); ok { - base := path.base(symbol.pkg, false, context.temp_allocator); + base := path.base(symbol.pkg, false, context.temp_allocator) item := CompletionItem { kind = .EnumMember, detail = fmt.tprintf("%v", selector.name), documentation = symbol.doc, - }; + } if symbol.pkg == ast_context.document_package || base == "runtime" { - item.label = fmt.aprintf("(%v)", common.node_to_string(type)); + item.label = fmt.aprintf("(%v)", common.node_to_string(type)) } else { - item.label = fmt.aprintf("(%v.%v)", path.base(symbol.pkg, false, context.temp_allocator), common.node_to_string(type)); + item.label = fmt.aprintf("(%v.%v)", path.base(symbol.pkg, false, context.temp_allocator), common.node_to_string(type)) } - append(&items, item); + append(&items, item) } } case index.SymbolEnumValue: - list.isIncomplete = false; + list.isIncomplete = false for name in v.names { item := CompletionItem { label = name, kind = .EnumMember, detail = fmt.tprintf("%v.%v", selector.name, name), - }; + } - append(&items, item); + append(&items, item) } case index.SymbolStructValue: - list.isIncomplete = false; + list.isIncomplete = false for name, i in v.names { if selector.pkg != "" { - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg } else { - ast_context.current_package = ast_context.document_package; + 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, ok := position_context.selector.derived.(^ast.Selector_Expr); ok { if expr.op.text == "->" && symbol.type != .Function { - continue; + continue } } if position_context.arrow && symbol.type != .Function { - continue; + continue } item := CompletionItem { @@ -410,9 +410,9 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v.%v: %v", selector.name, name, type_to_string(ast_context, v.types[i])), documentation = symbol.doc, - }; + } - append(&items, item); + append(&items, item) } else { //just give some generic symbol with name. item := CompletionItem { @@ -420,75 +420,75 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont kind = .Field, detail = fmt.tprintf("%v: %v", name, common.node_to_string(v.types[i])), documentation = symbol.doc, - }; + } - append(&items, item); + append(&items, item) } } case index.SymbolPackageValue: - list.isIncomplete = true; + list.isIncomplete = true if searched, ok := index.fuzzy_search(field, {selector.pkg}); ok { for search in searched { - symbol := search.symbol; + symbol := search.symbol - resolve_unresolved_symbol(ast_context, &symbol); - build_procedure_symbol_signature(&symbol); + resolve_unresolved_symbol(ast_context, &symbol) + build_procedure_symbol_signature(&symbol) item := CompletionItem { label = symbol.name, kind = cast(CompletionItemKind)symbol.type, detail = concatenate_symbol_information(ast_context, symbol, true), documentation = symbol.doc, - }; + } if symbol.type == .Function { - item.insertText = fmt.tprintf("%v($0)", item.label); - item.insertTextFormat = .Snippet; - item.command.command = "editor.action.triggerParameterHints"; - item.deprecated = .Deprecated in symbol.flags; + item.insertText = fmt.tprintf("%v($0)", item.label) + item.insertTextFormat = .Snippet + item.command.command = "editor.action.triggerParameterHints" + item.deprecated = .Deprecated in symbol.flags } - append(&items, item); + append(&items, item) } } else { - log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg); - return; + log.errorf("Failed to fuzzy search, field: %v, package: %v", field, selector.pkg) + return } } - list.items = items[:]; + list.items = items[:] } get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = false; + list.isIncomplete = false - selector: index.Symbol; + selector: index.Symbol - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true if selector.pkg != "" { - ast_context.current_package = selector.pkg; + ast_context.current_package = selector.pkg } else { - ast_context.current_package = ast_context.document_package; + 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); + used_enums := make(map[string]bool, 5, context.temp_allocator) - if block, ok := position_context.switch_stmt.body.derived.(ast.Block_Stmt); ok { + 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 { + 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 implicit, ok := name.derived.(^ast.Implicit_Selector_Expr); ok { + used_enums[implicit.field.name] = true } } } @@ -498,20 +498,20 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont 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; + continue } item := CompletionItem { label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } @@ -527,13 +527,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -549,13 +549,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -563,13 +563,17 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont //infer bitset and enums based on the identifier comp_lit, i.e. a := My_Struct { my_ident = . } if position_context.comp_lit != nil { if position_context.parent_comp_lit.type == nil { - return; + return } - field_name: string; + field_name: string if position_context.field_value != nil { - field_name = position_context.field_value.field.derived.(ast.Ident).name; + if field, ok := position_context.field_value.field.derived.(^ast.Ident); ok { + field_name = field.name + } else { + return + } } if symbol, ok := resolve_type_expression(ast_context, position_context.parent_comp_lit.type); ok { @@ -577,27 +581,27 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont if s, ok := comp_symbol.value.(index.SymbolStructValue); ok { //We can either have the final - elem_index := -1; + elem_index := -1 for elem, i in comp_lit.elems { if position_in_node(elem, position_context.position) { - elem_index = i; + elem_index = i } } - type: ^ast.Expr; + type: ^ast.Expr for name, i in s.names { if name != field_name { - continue; + continue } - type = s.types[i]; - break; + type = s.types[i] + break } if type == nil && len(s.types) > elem_index { - type = s.types[elem_index]; + type = s.types[elem_index] } if enum_value, ok := unwrap_enum(ast_context, type); ok { @@ -606,13 +610,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = enum_name, kind = .EnumMember, detail = enum_name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } else if bitset_symbol, ok := resolve_type_expression(ast_context, type); ok { if value, ok := unwrap_bitset(ast_context, bitset_symbol); ok { for name in value.names { @@ -621,12 +625,12 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -635,15 +639,15 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont } if position_context.binary != nil && (position_context.binary.op.text == "==" || position_context.binary.op.text == "!=") { - context_node: ^ast.Expr; - enum_node: ^ast.Expr; + context_node: ^ast.Expr + enum_node: ^ast.Expr if position_in_node(position_context.binary.right, position_context.position) { - context_node = position_context.binary.right; - enum_node = position_context.binary.left; + 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; + context_node = position_context.binary.left + enum_node = position_context.binary.right } if context_node != nil && enum_node != nil { @@ -653,34 +657,34 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.assign != nil && position_context.assign.rhs != nil && position_context.assign.lhs != nil { - rhs_index: int; + rhs_index: int for elem in position_context.assign.rhs { if position_in_node(elem, position_context.position) { - break; + break } else { //procedures are the only types that can return more than one value if symbol, ok := resolve_type_expression(ast_context, elem); ok { if procedure, ok := symbol.value.(index.SymbolProcedureValue); ok { if procedure.return_types == nil { - return; + return } - rhs_index += len(procedure.return_types); + rhs_index += len(procedure.return_types) } else { - rhs_index += 1; + rhs_index += 1 } } } @@ -693,37 +697,37 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.returns != nil && position_context.function != nil { - return_index: int; + return_index: int if position_context.returns.results == nil { - return; + return } for result, i in position_context.returns.results { if position_in_node(result, position_context.position) { - return_index = i; - break; + return_index = i + break } } if position_context.function.type == nil { - return; + return } if position_context.function.type.results == nil { - return; + return } if len(position_context.function.type.results.list) > return_index { @@ -733,24 +737,24 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } if position_context.call != nil { - if call, ok := position_context.call.derived.(ast.Call_Expr); ok { - parameter_index, parameter_ok := find_position_in_call_param(ast_context, call); + if call, ok := position_context.call.derived.(^ast.Call_Expr); ok { + parameter_index, parameter_ok := find_position_in_call_param(ast_context, call^) if symbol, ok := resolve_type_expression(ast_context, call.expr); ok && parameter_ok { if proc_value, ok := symbol.value.(index.SymbolProcedureValue); ok { if len(proc_value.arg_types) <= parameter_index { - return; + return } if enum_value, ok := unwrap_enum(ast_context, proc_value.arg_types[parameter_index].type); ok { @@ -759,13 +763,13 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont label = name, kind = .EnumMember, detail = name, - }; + } - append(&items, item); + append(&items, item) } - list.items = items[:]; - return; + list.items = items[:] + return } } } @@ -774,11 +778,11 @@ get_implicit_completion :: proc(ast_context: ^analysis.AstContext, position_cont } get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = true; + list.isIncomplete = true CombinedResult :: struct { score: f32, @@ -789,51 +793,51 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co pkg: string, signature: string, flags: index.SymbolFlags, - }; + } 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^); + 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; + 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]; + s := (^[dynamic]CombinedResult)(it.collection) + s[i], s[j] = s[j], s[i] }, - }; - }; + } + } - combined := make([dynamic]CombinedResult); + combined := make([dynamic]CombinedResult) - lookup := ""; + lookup := "" if position_context.identifier != nil { - if ident, ok := position_context.identifier.derived.(ast.Ident); ok { - lookup = ident.name; + if ident, ok := position_context.identifier.derived.(^ast.Ident); ok { + lookup = ident.name } } - pkgs := make([dynamic]string, context.temp_allocator); + pkgs := make([dynamic]string, context.temp_allocator) - usings := get_using_packages(ast_context); + usings := get_using_packages(ast_context) for u in usings { - append(&pkgs, u); + append(&pkgs, u) } - append(&pkgs, ast_context.document_package); + append(&pkgs, ast_context.document_package) if results, ok := index.fuzzy_search(lookup, pkgs[:]); ok { for r in results { - r := r; - resolve_unresolved_symbol(ast_context, &r.symbol); - build_procedure_symbol_signature(&r.symbol); + r := r + resolve_unresolved_symbol(ast_context, &r.symbol) + build_procedure_symbol_signature(&r.symbol) if r.symbol.uri != ast_context.uri { append(&combined, CombinedResult { score = r.score, @@ -843,36 +847,36 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = r.symbol.flags, signature = r.symbol.signature, pkg = r.symbol.pkg, - }); + }) } } } - matcher := common.make_fuzzy_matcher(lookup); + matcher := common.make_fuzzy_matcher(lookup) global: for k, v in ast_context.globals { if position_context.global_lhs_stmt { - break; + break } //combined is sorted and should do binary search instead. for result in combined { if result.name == k { - continue global; + 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.expr.pos, v.expr.end, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, v.expr.pos, v.expr.end, context.temp_allocator) + ident.name = k if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.signature = get_signature(ast_context, ident^, symbol); + symbol.signature = get_signature(ast_context, ident^, symbol) - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { append(&combined, CombinedResult { @@ -883,7 +887,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, pkg = symbol.pkg, signature = symbol.signature, - }); + }) } } } @@ -891,22 +895,22 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co for _, local in ast_context.locals { for k, v in local { if position_context.global_lhs_stmt { - break; + break } - local_offset := get_local_offset(ast_context, position_context.position, k); + local_offset := get_local_offset(ast_context, position_context.position, k) - 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, {offset = local_offset}, {offset = local_offset}, context.temp_allocator); - ident.name = k; + ident := index.new_type(ast.Ident, {offset = local_offset}, {offset = local_offset}, context.temp_allocator) + ident.name = k if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { - symbol.signature = get_signature(ast_context, ident^, symbol); + symbol.signature = get_signature(ast_context, ident^, symbol) - build_procedure_symbol_signature(&symbol); + build_procedure_symbol_signature(&symbol) if score, ok := common.fuzzy_match(matcher, ident.name); ok == 1 { append(&combined, CombinedResult { @@ -917,7 +921,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, pkg = symbol.pkg, signature = symbol.signature, - }); + }) } } } @@ -925,13 +929,13 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co for pkg in ast_context.imports { if position_context.global_lhs_stmt { - break; + break } symbol := index.Symbol { name = pkg.base, type = .Package, - }; + } if score, ok := common.fuzzy_match(matcher, symbol.name); ok == 1 { append(&combined, CombinedResult { @@ -942,7 +946,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } @@ -950,7 +954,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co symbol := index.Symbol { name = keyword, type = .Keyword, - }; + } if score, ok := common.fuzzy_match(matcher, keyword); ok == 1 { append(&combined, CombinedResult { @@ -961,7 +965,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } @@ -969,7 +973,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co symbol := index.Symbol { name = keyword, type = .Keyword, - }; + } if score, ok := common.fuzzy_match(matcher, keyword); ok == 1 { append(&combined, CombinedResult { @@ -980,29 +984,29 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co flags = symbol.flags, signature = symbol.signature, pkg = symbol.pkg, - }); + }) } } if common.config.enable_snippets { for k, v in snippets { if score, ok := common.fuzzy_match(matcher, k); ok == 1 { - append(&combined, CombinedResult {score = score * 1.1, snippet = v, name = k}); + append(&combined, CombinedResult {score = score * 1.1, snippet = v, name = k}) } } } - sort.sort(combined_sort_interface(&combined)); + sort.sort(combined_sort_interface(&combined)) //hard code for now - top_results := combined[0:(min(50, len(combined)))]; + top_results := combined[0:(min(50, len(combined)))] for result in top_results { - result := result; + result := result //Skip procedures when the position is in proc decl if position_in_proc_decl(position_context) && result.type == .Function && common.config.enable_procedure_context { - continue; + continue } if result.snippet.insert != "" { @@ -1012,72 +1016,72 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co kind = .Snippet, detail = result.snippet.detail, insertTextFormat = .Snippet, - }; + } - edits := make([dynamic]TextEdit, context.temp_allocator); + edits := make([dynamic]TextEdit, context.temp_allocator) for pkg in result.snippet.packages { - edit, ok := get_core_insert_package_if_non_existent(ast_context, pkg); + edit, ok := get_core_insert_package_if_non_existent(ast_context, pkg) if ok { - append(&edits, edit); + append(&edits, edit) } } - item.additionalTextEdits = edits[:]; + item.additionalTextEdits = edits[:] - append(&items, item); + append(&items, item) } else { item := CompletionItem { label = result.name, documentation = result.doc, - }; + } - item.kind = cast(CompletionItemKind)result.type; + item.kind = cast(CompletionItemKind)result.type if result.type == .Function { - item.insertText = fmt.tprintf("%v($0)", item.label); - item.insertTextFormat = .Snippet; - item.deprecated = .Deprecated in result.flags; - item.command.command = "editor.action.triggerParameterHints"; + item.insertText = fmt.tprintf("%v($0)", item.label) + item.insertTextFormat = .Snippet + item.deprecated = .Deprecated in result.flags + item.command.command = "editor.action.triggerParameterHints" } - item.detail = concatenate_symbol_information(ast_context, result.pkg, result.name, result.signature, result.type, true); + item.detail = concatenate_symbol_information(ast_context, result.pkg, result.name, result.signature, result.type, true) - append(&items, item); + append(&items, item) } } - list.items = items[:]; + list.items = items[:] } get_package_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - items := make([dynamic]CompletionItem, context.temp_allocator); + items := make([dynamic]CompletionItem, context.temp_allocator) - list.isIncomplete = false; + list.isIncomplete = false - fullpath_length := len(position_context.import_stmt.fullpath); + fullpath_length := len(position_context.import_stmt.fullpath) if fullpath_length <= 1 { - return; + return } - without_quotes := position_context.import_stmt.fullpath[1:fullpath_length-1]; - absolute_path := without_quotes; - colon_index := strings.index(without_quotes, ":"); + without_quotes := position_context.import_stmt.fullpath[1:fullpath_length-1] + absolute_path := without_quotes + colon_index := strings.index(without_quotes, ":") if colon_index >= 0 { - c := without_quotes[0:colon_index]; + c := without_quotes[0:colon_index] if colon_index+1 < len(without_quotes) { - absolute_path = filepath.join(elems = {common.config.collections[c], filepath.dir(without_quotes[colon_index+1:], context.temp_allocator)}, allocator = context.temp_allocator); + absolute_path = filepath.join(elems = {common.config.collections[c], filepath.dir(without_quotes[colon_index+1:], context.temp_allocator)}, allocator = context.temp_allocator) } else { - absolute_path = common.config.collections[c]; + absolute_path = common.config.collections[c] } } else { - import_file_dir := filepath.dir(position_context.import_stmt.pos.file, context.temp_allocator); - import_dir := filepath.dir(without_quotes, context.temp_allocator); - absolute_path = filepath.join(elems = {import_file_dir, import_dir}, allocator = context.temp_allocator); + import_file_dir := filepath.dir(position_context.import_stmt.pos.file, context.temp_allocator) + import_dir := filepath.dir(without_quotes, context.temp_allocator) + absolute_path = filepath.join(elems = {import_file_dir, import_dir}, allocator = context.temp_allocator) } if !strings.contains(position_context.import_stmt.fullpath, "/") && !strings.contains(position_context.import_stmt.fullpath, ":") { @@ -1087,9 +1091,9 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte detail = "collection", label = key, kind = .Module, - }; + } - append(&items, item); + append(&items, item) } } @@ -1099,103 +1103,103 @@ get_package_completion :: proc(ast_context: ^analysis.AstContext, position_conte detail = pkg, label = filepath.base(pkg), kind = .Folder, - }; + } if item.label[0] == '.' { - continue; + continue } - append(&items, item); + append(&items, item) } - list.items = items[:]; + list.items = items[:] } search_for_packages :: proc(fullpath: string) -> [] string { - packages := make([dynamic]string, context.temp_allocator); + packages := make([dynamic]string, context.temp_allocator) - fh, err := os.open(fullpath); + fh, err := os.open(fullpath) if err != 0 { - return {}; + return {} } if files, err := os.read_dir(fh, 0, context.temp_allocator); err == 0 { for file in files { if file.is_dir { - append(&packages, file.fullpath); + append(&packages, file.fullpath) } } } - return packages[:]; + return packages[:] } get_type_switch_completion :: proc(ast_context: ^analysis.AstContext, position_context: ^analysis.DocumentPositionContext, list: ^CompletionList) { - using analysis; + using analysis - items := make([dynamic]CompletionItem, context.temp_allocator); - list.isIncomplete = false; + items := make([dynamic]CompletionItem, context.temp_allocator) + list.isIncomplete = false - used_unions := make(map[string]bool, 5, context.temp_allocator); + used_unions := make(map[string]bool, 5, context.temp_allocator) - if block, ok := position_context.switch_type_stmt.body.derived.(ast.Block_Stmt); ok { + if block, ok := position_context.switch_type_stmt.body.derived.(^ast.Block_Stmt); ok { for stmt in block.stmts { - if case_clause, ok := stmt.derived.(ast.Case_Clause); ok { + if case_clause, ok := stmt.derived.(^ast.Case_Clause); ok { for name in case_clause.list { - if ident, ok := name.derived.(ast.Ident); ok { - used_unions[ident.name] = true; + if ident, ok := name.derived.(^ast.Ident); ok { + used_unions[ident.name] = true } } } } } - ast_context.use_locals = true; - ast_context.use_globals = true; + ast_context.use_locals = true + ast_context.use_globals = true - 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 { for type, i in union_value.types { - name := common.node_to_string(type); + name := common.node_to_string(type) if name in used_unions { - continue; + continue } if symbol, ok := resolve_type_expression(ast_context, union_value.types[i]); ok { item := CompletionItem { kind = .EnumMember, - }; + } if symbol.pkg == ast_context.document_package { - item.label = fmt.aprintf("%v", common.node_to_string(union_value.types[i])); - item.detail = item.label; + item.label = fmt.aprintf("%v", common.node_to_string(union_value.types[i])) + item.detail = item.label } else { - item.label = fmt.aprintf("%v.%v", path.base(symbol.pkg, false, context.temp_allocator), name); - item.detail = item.label; + item.label = fmt.aprintf("%v.%v", path.base(symbol.pkg, false, context.temp_allocator), name) + item.detail = item.label } - append(&items, item); + append(&items, item) } } } } - list.items = items[:]; + list.items = items[:] } get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContext, pkg: string) -> (TextEdit, bool) { - builder := strings.make_builder(context.temp_allocator); + builder := strings.make_builder(context.temp_allocator) for imp in ast_context.imports { if imp.base == pkg { - return {}, false; + return {}, false } } - strings.write_string(&builder, fmt.tprintf("import \"core:%v\"", pkg)); + strings.write_string(&builder, fmt.tprintf("import \"core:%v\"", pkg)) return { newText = strings.to_string(builder), @@ -1209,7 +1213,7 @@ get_core_insert_package_if_non_existent :: proc(ast_context: ^analysis.AstContex character = 0, }, }, - }, true; + }, true } bitset_operators: map[string]bool = { @@ -1219,7 +1223,7 @@ bitset_operators: map[string]bool = { "<" = true, ">" = true, "==" = true, -}; +} bitset_assignment_operators: map[string]bool = { "|=" = true, @@ -1228,14 +1232,14 @@ bitset_assignment_operators: map[string]bool = { "<=" = true, ">=" = true, "=" = true, -}; +} is_bitset_binary_operator :: proc(op: string) -> bool { - return op in bitset_operators; + return op in bitset_operators } is_bitset_assignment_operator :: proc(op: string) -> bool { - return op in bitset_assignment_operators; + return op in bitset_assignment_operators } language_keywords: []string = { @@ -1280,14 +1284,14 @@ language_keywords: []string = { "using", "or_return", "or_else", -}; +} swizzle_color_components: map[u8]bool = { 'r' = true, 'g' = true, 'b' = true, 'a' = true, -}; +} swizzle_coord_components: map[u8]bool = { 'x' = true, |