aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/analysis.odin80
-rw-r--r--src/server/collector.odin131
-rw-r--r--src/server/completion.odin12
-rw-r--r--src/server/memory_index.odin8
-rw-r--r--src/server/requests.odin6
-rw-r--r--src/server/symbol.odin13
6 files changed, 214 insertions, 36 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index 142ee38..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
@@ -1308,7 +1310,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,
@@ -1410,14 +1430,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 +1971,37 @@ expand_struct_usings :: proc(
}
}
+ if .ObjC in symbol.flags {
+ pkg := indexer.index.collection.packages[symbol.pkg]
+
+ 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 = obj_struct.pkg
+
+ 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)
+ append(&ranges, obj_struct.ranges[i])
+ }
+
+ }
+
+ //fmt.println(symbol.name)
+ }
+
return {names = names[:], types = types[:], ranges = ranges[:]}
}
@@ -2024,7 +2070,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 +2490,13 @@ make_symbol_procedure_from_ast :: proc(
generic = v.generic,
}
+ 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
}
@@ -2734,12 +2787,19 @@ make_symbol_struct_from_ast :: proc(
usings = usings,
}
+ 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 {
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,
diff --git a/src/server/collector.odin b/src/server/collector.odin
index b065a9e..89ec7f6 100644
--- a/src/server/collector.odin
+++ b/src/server/collector.odin
@@ -15,10 +15,26 @@ import "shared:common"
SymbolCollection :: struct {
allocator: mem.Allocator,
config: ^common.Config,
- packages: map[string]map[string]Symbol,
+ packages: map[string]SymbolPackage,
unique_strings: map[string]string, //store all our strings as unique strings and reference them to save memory.
}
+ObjcFunction :: struct {
+ physical_name: string,
+ logical_name: string,
+}
+
+ObjcStruct :: struct {
+ functions: [dynamic]ObjcFunction,
+ pkg: string,
+ ranges: [dynamic]common.Range,
+}
+
+SymbolPackage :: struct {
+ symbols: map[string]Symbol,
+ objc_structs: map[string]ObjcStruct, //mapping from struct name to function
+}
+
get_index_unique_string :: proc {
get_index_unique_string_collection,
get_index_unique_string_collection_raw,
@@ -56,7 +72,7 @@ make_symbol_collection :: proc(
SymbolCollection{
allocator = allocator,
config = config,
- packages = make(map[string]map[string]Symbol, 16, allocator),
+ packages = make(map[string]SymbolPackage, 16, allocator),
unique_strings = make(map[string]string, 16, allocator),
} \
)
@@ -64,7 +80,7 @@ make_symbol_collection :: proc(
delete_symbol_collection :: proc(collection: SymbolCollection) {
for k, v in collection.packages {
- for k2, v2 in v {
+ for k2, v2 in v.symbols {
free_symbol(v2, collection.allocator)
}
}
@@ -74,7 +90,7 @@ delete_symbol_collection :: proc(collection: SymbolCollection) {
}
for k, v in collection.packages {
- delete(v)
+ delete(v.symbols)
}
delete(collection.packages)
@@ -87,6 +103,7 @@ collect_procedure_fields :: proc(
arg_list: ^ast.Field_List,
return_list: ^ast.Field_List,
package_map: map[string]string,
+ attributes: []^ast.Attribute,
) -> SymbolProcedureValue {
returns := make([dynamic]^ast.Field, 0, collection.allocator)
args := make([dynamic]^ast.Field, 0, collection.allocator)
@@ -119,7 +136,16 @@ collect_procedure_fields :: proc(
return_types = returns[:],
arg_types = args[:],
generic = proc_type.generic,
+ /*
+ objc_name = common.get_attribute_objc_name(
+ attributes,
+ ) or_else "",
+ objc_is_class_method = common.get_attribute_objc_is_class_method(
+ attributes,
+ ) or_else false,
+ */
}
+
return value
}
@@ -407,6 +433,64 @@ collect_generic :: proc(
return value
}
+collect_objc :: proc(
+ collection: ^SymbolCollection,
+ attributes: []^ast.Attribute,
+ symbol: Symbol,
+) {
+ pkg := &collection.packages[symbol.pkg]
+
+ if value, ok := symbol.value.(SymbolProcedureValue); ok {
+ objc_name, found_objc_name := common.get_attribute_objc_name(
+ attributes,
+ )
+
+ if objc_type := common.get_attribute_objc_type(attributes);
+ objc_type != nil && found_objc_name {
+
+ if struct_ident, ok := objc_type.derived.(^ast.Ident); ok {
+ struct_name := get_index_unique_string_collection(
+ collection,
+ struct_ident.name,
+ )
+
+ objc_struct := &pkg.objc_structs[struct_name]
+
+ 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,
+ )
+ objc_struct.ranges = make(
+ [dynamic]common.Range,
+ 0,
+ 10,
+ collection.allocator,
+ )
+ objc_struct.pkg = symbol.pkg
+ }
+
+ append(&objc_struct.ranges, symbol.range)
+
+ append(
+ &objc_struct.functions,
+ ObjcFunction{
+ logical_name = get_index_unique_string_collection(
+ collection,
+ objc_name,
+ ),
+ physical_name = symbol.name,
+ },
+ )
+ }
+ }
+ }
+}
+
collect_symbols :: proc(
collection: ^SymbolCollection,
file: ast.File,
@@ -456,8 +540,17 @@ collect_symbols :: proc(
v.type.params,
v.type.results,
package_map,
+ expr.attributes,
)
}
+
+ 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^
token_type = .Function
@@ -467,6 +560,7 @@ collect_symbols :: proc(
v.params,
v.results,
package_map,
+ expr.attributes,
)
case ^ast.Proc_Group:
token = v^
@@ -488,6 +582,15 @@ collect_symbols :: proc(
file,
)
symbol.signature = "struct"
+
+ if _, is_objc := common.get_attribute_objc_class_name(
+ 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^
token_type = .Enum
@@ -611,20 +714,26 @@ collect_symbols :: proc(
symbol.uri = get_index_unique_string(collection, uri)
- pkg: ^map[string]Symbol
+ pkg: ^SymbolPackage
ok: bool
if pkg, ok = &collection.packages[symbol.pkg]; !ok {
- collection.packages[symbol.pkg] = make(
- map[string]Symbol,
- 100,
+ collection.packages[symbol.pkg] = {}
+ pkg = &collection.packages[symbol.pkg]
+ pkg.symbols = make(map[string]Symbol, 100, collection.allocator)
+ pkg.objc_structs = make(
+ map[string]ObjcStruct,
+ 5,
collection.allocator,
)
- pkg = &collection.packages[symbol.pkg]
}
- if v, ok := pkg[symbol.name]; !ok || v.name == "" {
- pkg[symbol.name] = symbol
+ if .ObjC in symbol.flags {
+ collect_objc(collection, expr.attributes, symbol)
+ }
+
+ if v, ok := pkg.symbols[symbol.name]; !ok || v.name == "" {
+ pkg.symbols[symbol.name] = symbol
} else {
free_symbol(symbol, collection.allocator)
}
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/memory_index.odin b/src/server/memory_index.odin
index a211b94..d803a24 100644
--- a/src/server/memory_index.odin
+++ b/src/server/memory_index.odin
@@ -36,9 +36,9 @@ memory_index_lookup :: proc(
}
if _pkg, ok := &index.collection.packages[pkg]; ok {
- index.last_package = _pkg
+ index.last_package = &_pkg.symbols
index.last_package_name = pkg
- return _pkg[name]
+ return _pkg.symbols[name]
} else {
index.last_package = nil
index.last_package_name = ""
@@ -63,9 +63,9 @@ memory_index_fuzzy_search :: proc(
for pkg in pkgs {
if pkg, ok := index.collection.packages[pkg]; ok {
- for _, symbol in pkg {
+ for _, symbol in pkg.symbols {
if score, ok := common.fuzzy_match(fuzzy_matcher, symbol.name);
- ok == 1 {
+ ok == 1 {
result := FuzzyResult {
symbol = symbol,
score = score,
diff --git a/src/server/requests.odin b/src/server/requests.odin
index 9630c0b..b9ac631 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -907,7 +907,7 @@ notification_did_change :: proc(
writer: ^Writer,
) -> common.Error {
params_object, ok := params.(json.Object)
-
+
if !ok {
return .ParseError
}
@@ -1023,10 +1023,10 @@ notification_did_save :: proc(
corrected_uri := common.create_uri(fullpath, context.temp_allocator)
for k, v in &indexer.index.collection.packages {
- for k2, v2 in &v {
+ for k2, v2 in &v.symbols {
if corrected_uri.uri == v2.uri {
free_symbol(v2, indexer.index.collection.allocator)
- v[k2] = {}
+ v.symbols[k2] = {}
}
}
}
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 8f7a081..ce3509d 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -17,13 +17,11 @@ SymbolAndNode :: struct {
}
SymbolStructValue :: struct {
- names: []string,
- ranges: []common.Range,
- types: []^ast.Expr,
- usings: map[string]bool,
- poly: ^ast.Field_List,
- objc_name: string,
- objc_is_class_method: bool,
+ names: []string,
+ ranges: []common.Range,
+ types: []^ast.Expr,
+ usings: map[string]bool,
+ poly: ^ast.Field_List,
}
SymbolPackageValue :: struct {}
@@ -133,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]