From cf21683e4cc90cf620957c5e3141d5d3b51f399a Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Mon, 23 Jan 2023 23:38:13 +0100 Subject: start working on supporting objc code --- src/server/analysis.odin | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 142ee38..efcd7ca 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1410,14 +1410,9 @@ internal_resolve_type_expression :: proc( return Symbol{}, false } } - } else { - return Symbol{}, false } case: log.warnf("default node kind, internal_resolve_type_expression: %T", v) - if v == nil { - return {}, false - } } return Symbol{}, false @@ -1956,6 +1951,36 @@ expand_struct_usings :: proc( } } + if .ObjC in symbol.flags { + pkg := indexer.index.collection.packages[symbol.pkg] + + if functions, ok := pkg.objc_structs[symbol.name]; ok { + for function in functions { + base := new_type(ast.Ident, {}, {}, context.temp_allocator) + base.name = pkg.objc_package[symbol.name] + + field := new_type(ast.Ident, {}, {}, context.temp_allocator) + field.name = function.physical_name + + selector := new_type( + ast.Selector_Expr, + {}, + {}, + context.temp_allocator, + ) + + selector.field = field + selector.expr = base + + append(&names, function.logical_name) + append(&types, selector) + } + + } + + //fmt.println(symbol.name) + } + return {names = names[:], types = types[:], ranges = ranges[:]} } @@ -2024,7 +2049,7 @@ resolve_symbol_return :: proc( } //expand the types and names from the using - can't be done while indexing without complicating everything(this also saves memory) - if len(v.usings) > 0 { + if len(v.usings) > 0 || .ObjC in symbol.flags { expanded := symbol expanded.value = expand_struct_usings(ast_context, symbol, v) return expanded, true @@ -2444,6 +2469,10 @@ make_symbol_procedure_from_ast :: proc( generic = v.generic, } + if _, ok := common.get_attribute_objc_name(attributes); ok { + symbol.flags |= {.ObjC} + } + return symbol } @@ -2734,12 +2763,16 @@ make_symbol_struct_from_ast :: proc( usings = usings, } + if _, ok := common.get_attribute_objc_class_name(attributes); ok { + symbol.flags |= {.ObjC} + } + if v.poly_params != nil { resolve_poly_struct(ast_context, v.poly_params, &symbol) } //TODO change the expand to not double copy the array, but just pass the dynamic arrays - if len(usings) > 0 { + if len(usings) > 0 || .ObjC in symbol.flags { symbol.value = expand_struct_usings( ast_context, symbol, -- cgit v1.2.3 From 0024759da37e17611e1b91510bc2b6939c9cb310 Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Mon, 23 Jan 2023 23:45:53 +0100 Subject: early support of goto for objc --- src/server/analysis.odin | 7 ++++--- src/server/collector.odin | 36 ++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index efcd7ca..df6ce4a 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1954,10 +1954,10 @@ expand_struct_usings :: proc( if .ObjC in symbol.flags { pkg := indexer.index.collection.packages[symbol.pkg] - if functions, ok := pkg.objc_structs[symbol.name]; ok { - for function in functions { + if obj_struct, ok := pkg.objc_structs[symbol.name]; ok { + for function, i in obj_struct.functions { base := new_type(ast.Ident, {}, {}, context.temp_allocator) - base.name = pkg.objc_package[symbol.name] + base.name = obj_struct.pkg field := new_type(ast.Ident, {}, {}, context.temp_allocator) field.name = function.physical_name @@ -1974,6 +1974,7 @@ expand_struct_usings :: proc( append(&names, function.logical_name) append(&types, selector) + append(&ranges, obj_struct.ranges[i]) } } diff --git a/src/server/collector.odin b/src/server/collector.odin index 42f97c2..e34458c 100644 --- a/src/server/collector.odin +++ b/src/server/collector.odin @@ -24,10 +24,15 @@ ObjcFunction :: struct { logical_name: string, } +ObjcStruct :: struct { + functions: [dynamic]ObjcFunction, + pkg: string, + ranges: [dynamic]common.Range, +} + SymbolPackage :: struct { symbols: map[string]Symbol, - objc_structs: map[string][dynamic]ObjcFunction, //mapping from struct name to function - objc_package: map[string]string, //which package the struct lives in - this is necessery to prevent resolving types at indexing time + objc_structs: map[string]ObjcStruct, //mapping from struct name to function } get_index_unique_string :: proc { @@ -449,26 +454,30 @@ collect_objc :: proc( struct_ident.name, ) - functions := &pkg.objc_structs[struct_name] + objc_struct := &pkg.objc_structs[struct_name] - if functions == nil { - pkg.objc_structs[struct_name] = make( + if objc_struct == nil { + pkg.objc_structs[struct_name] = {} + objc_struct = &pkg.objc_structs[struct_name] + objc_struct.functions = make( [dynamic]ObjcFunction, 0, 10, collection.allocator, ) - functions = &pkg.objc_structs[struct_name] - } - - if struct_name not_in pkg.objc_package { - pkg.objc_package[struct_name] = symbol.pkg + objc_struct.ranges = make( + [dynamic]common.Range, + 0, + 10, + collection.allocator, + ) + objc_struct.pkg = symbol.pkg } - log.error(symbol.name) + append(&objc_struct.ranges, symbol.range) append( - functions, + &objc_struct.functions, ObjcFunction{ logical_name = get_index_unique_string_collection( collection, @@ -707,11 +716,10 @@ collect_symbols :: proc( pkg = &collection.packages[symbol.pkg] pkg.symbols = make(map[string]Symbol, 100, collection.allocator) pkg.objc_structs = make( - map[string][dynamic]ObjcFunction, + map[string]ObjcStruct, 5, collection.allocator, ) - pkg.objc_package = make(map[string]string, 5, collection.allocator) } if .ObjC in symbol.flags { -- cgit v1.2.3 From 425a81e728aabed07d46c22c1f1dfae5958b8b62 Mon Sep 17 00:00:00 2001 From: Lucas Perlind Date: Tue, 24 Jan 2023 21:48:33 +1100 Subject: More accurately auto complete ObjC procedures --- src/common/ast.odin | 19 ++++++++++++++++--- src/server/analysis.odin | 6 ++++++ src/server/collector.odin | 8 +++++++- src/server/completion.odin | 12 +++++++++++- src/server/symbol.odin | 1 + 5 files changed, 41 insertions(+), 5 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/common/ast.odin b/src/common/ast.odin index c589f49..158882d 100644 --- a/src/common/ast.odin +++ b/src/common/ast.odin @@ -143,13 +143,26 @@ get_attribute_objc_class_name :: proc( } -get_attribute_objc_class_method :: proc( +get_attribute_objc_is_class_method :: proc( attributes: []^ast.Attribute, ) -> ( bool, - bool, ) { - return false, false + for attribute in attributes { + for elem in attribute.elems { + if assign, ok := elem.derived.(^ast.Field_Value); ok { + if ident, ok := assign.field.derived.(^ast.Ident); + ok && ident.name == "objc_is_class_method" { + if field_value, ok := assign.value.derived.(^ast.Ident); + ok && field_value.name == "true" { + return true + } + } + + } + } + } + return false } unwrap_pointer :: proc(expr: ^ast.Expr) -> (ast.Ident, bool) { diff --git a/src/server/analysis.odin b/src/server/analysis.odin index df6ce4a..ff42709 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -2472,6 +2472,9 @@ make_symbol_procedure_from_ast :: proc( if _, ok := common.get_attribute_objc_name(attributes); ok { symbol.flags |= {.ObjC} + if common.get_attribute_objc_is_class_method(attributes) { + symbol.flags |= {.ObjCIsClassMethod} + } } return symbol @@ -2766,6 +2769,9 @@ make_symbol_struct_from_ast :: proc( if _, ok := common.get_attribute_objc_class_name(attributes); ok { symbol.flags |= {.ObjC} + if common.get_attribute_objc_is_class_method(attributes) { + symbol.flags |= {.ObjCIsClassMethod} + } } if v.poly_params != nil { diff --git a/src/server/collector.odin b/src/server/collector.odin index e34458c..89ec7f6 100644 --- a/src/server/collector.odin +++ b/src/server/collector.odin @@ -140,7 +140,7 @@ collect_procedure_fields :: proc( objc_name = common.get_attribute_objc_name( attributes, ) or_else "", - objc_is_class_method = common.get_attribute_objc_class_method( + objc_is_class_method = common.get_attribute_objc_is_class_method( attributes, ) or_else false, */ @@ -547,6 +547,9 @@ collect_symbols :: proc( if _, is_objc := common.get_attribute_objc_name(expr.attributes); is_objc { symbol.flags |= {.ObjC} + if common.get_attribute_objc_is_class_method(expr.attributes) { + symbol.flags |= {.ObjCIsClassMethod} + } } case ^ast.Proc_Type: token = v^ @@ -584,6 +587,9 @@ collect_symbols :: proc( expr.attributes, ); is_objc { symbol.flags |= {.ObjC} + if common.get_attribute_objc_is_class_method(expr.attributes) { + symbol.flags |= {.ObjCIsClassMethod} + } } case ^ast.Enum_Type: token = v^ diff --git a/src/server/completion.odin b/src/server/completion.odin index 7c3b397..d81aac7 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -519,10 +519,20 @@ get_selector_completion :: proc( } } - if position_context.arrow && symbol.type != .Function { + if position_context.arrow { + if symbol.type != .Function { + continue + } + if .ObjCIsClassMethod in symbol.flags { + assert(.ObjC in symbol.flags) + continue + } + } + if !position_context.arrow && .ObjC in symbol.flags { continue } + item := CompletionItem { label = name, kind = .Field, diff --git a/src/server/symbol.odin b/src/server/symbol.odin index dffa10a..ce3509d 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -131,6 +131,7 @@ SymbolFlag :: enum { Variable, //Symbols that are variable, this means their value decl was mutable Local, ObjC, + ObjCIsClassMethod, // should be set true only when ObjC is enabled } SymbolFlags :: bit_set[SymbolFlag] -- cgit v1.2.3 From 74acfe4fa2fd9a1c8636c3666b8fea38ebdef727 Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Tue, 24 Jan 2023 20:44:39 +0100 Subject: Fixed error where `->` with call expression couldn't be resolved --- src/server/analysis.odin | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index ff42709..25dc2ef 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1308,7 +1308,25 @@ internal_resolve_type_expression :: proc( case ^Implicit_Selector_Expr: return Symbol{}, false case ^Selector_Call_Expr: - return internal_resolve_type_expression(ast_context, v.expr) + if selector, ok := internal_resolve_type_expression( + ast_context, + v.expr, + ); ok { + ast_context.use_locals = false + ast_context.current_package = selector.pkg + + #partial switch s in selector.value { + case SymbolProcedureValue: + if len(s.return_types) == 1 { + return internal_resolve_type_expression( + ast_context, + s.return_types[0].type, + ) + } + } + + return selector, true + } case ^Selector_Expr: if selector, ok := internal_resolve_type_expression( ast_context, -- cgit v1.2.3 From 5aba6a1d6ddb2998183f407ec502ecf2c08854ca Mon Sep 17 00:00:00 2001 From: DanielGavin Date: Sat, 25 Feb 2023 20:41:17 +0100 Subject: use internal resolve in resolve_function_overload to prevent recursion. --- src/server/analysis.odin | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/server/analysis.odin') diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 25dc2ef..eb24321 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -866,8 +866,10 @@ resolve_function_overload :: proc( candidates := make([dynamic]Symbol, context.temp_allocator) for arg_expr in group.args { - next_fn: if f, ok := resolve_type_expression(ast_context, arg_expr); - ok { + next_fn: if f, ok := internal_resolve_type_expression( + ast_context, + arg_expr, + ); ok { if call_expr == nil || len(call_expr.args) == 0 { append(&candidates, f) break next_fn -- cgit v1.2.3