aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analysis/analysis.odin63
-rw-r--r--src/index/collector.odin15
-rw-r--r--src/index/symbol.odin15
-rw-r--r--src/server/completion.odin7
-rw-r--r--tests/completions_test.odin45
5 files changed, 122 insertions, 23 deletions
diff --git a/src/analysis/analysis.odin b/src/analysis/analysis.odin
index b6f4e70..09bfb3a 100644
--- a/src/analysis/analysis.odin
+++ b/src/analysis/analysis.odin
@@ -538,12 +538,12 @@ is_symbol_same_typed :: proc(ast_context: ^AstContext, a, b: index.Symbol, flags
return false;
}
- if a.is_distinct != b.is_distinct {
+ if .Distinct in a.flags != .Distinct in b.flags {
return false;
}
- if a.is_distinct == b.is_distinct &&
- a.is_distinct == true &&
+ if .Distinct in a.flags == .Distinct in b.flags &&
+ .Distinct in a.flags &&
a.name == b.name &&
a.pkg == b.pkg {
return true;
@@ -829,6 +829,14 @@ resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Expr) -> (i
using ast;
switch v in &node.derived {
+ case Union_Type:
+ return make_symbol_union_from_ast(ast_context, v, ast_context.field_name, true), true;
+ case Enum_Type:
+ return make_symbol_enum_from_ast(ast_context, v, ast_context.field_name, true), true;
+ case Struct_Type:
+ return make_symbol_struct_from_ast(ast_context, v, ast_context.field_name, true), true;
+ case Bit_Set_Type:
+ return make_symbol_bitset_from_ast(ast_context, v, ast_context.field_name, true), true;
case Array_Type:
return make_symbol_array_from_ast(ast_context, v), true;
case Dynamic_Array_Type:
@@ -1113,7 +1121,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
if is_distinct {
return_symbol.name = node.name;
- return_symbol.is_distinct = is_distinct;
+ return_symbol.flags |= {.Distinct};
}
return return_symbol, ok;
@@ -1171,7 +1179,7 @@ resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ident) -> (i
if is_distinct {
return_symbol.name = node.name;
- return_symbol.is_distinct = is_distinct;
+ return_symbol.flags |= {.Distinct};
}
return_symbol.doc = common.get_doc(global.docs, context.temp_allocator);
@@ -1579,7 +1587,9 @@ make_symbol_procedure_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node, v
}
if expr, ok := ast_context.globals[name]; ok {
- symbol.is_deprecated = expr.deprecated;
+ if expr.deprecated {
+ symbol.flags |= {.Distinct};
+ }
}
symbol.value = index.SymbolProcedureValue {
@@ -1658,7 +1668,7 @@ make_symbol_basic_type_from_ast :: proc(ast_context: ^AstContext, n: ^ast.Node,
return symbol;
}
-make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type, ident: string) -> index.Symbol {
+make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type, ident: string, inlined := false) -> index.Symbol {
symbol := index.Symbol {
range = common.get_token_range(v, ast_context.file.src),
@@ -1666,6 +1676,11 @@ make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type,
pkg = get_package_from_node(v.node),
};
+ if inlined {
+ symbol.flags |= {.Anonymous};
+ symbol.name = "union";
+ }
+
names := make([dynamic]string, context.temp_allocator);
for variant in v.variants {
@@ -1689,14 +1704,19 @@ make_symbol_union_from_ast :: proc(ast_context: ^AstContext, v: ast.Union_Type,
return symbol;
}
-make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, ident: string) -> index.Symbol {
-
+make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, ident: string, inlined := false) -> index.Symbol {
symbol := index.Symbol {
range = common.get_token_range(v, ast_context.file.src),
type = .Enum,
pkg = get_package_from_node(v.node),
};
+ if inlined {
+ symbol.flags |= {.Anonymous};
+ symbol.name = "enum";
+ }
+
+
names := make([dynamic]string, context.temp_allocator);
for n in v.fields {
@@ -1719,7 +1739,7 @@ make_symbol_enum_from_ast :: proc(ast_context: ^AstContext, v: ast.Enum_Type, id
return symbol;
}
-make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Type, ident: string) -> index.Symbol {
+make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Type, ident: string, inlined := false) -> index.Symbol {
symbol := index.Symbol {
range = common.get_token_range(v, ast_context.file.src),
@@ -1727,6 +1747,11 @@ make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Typ
pkg = get_package_from_node(v.node),
};
+ if inlined {
+ symbol.flags |= {.Anonymous};
+ symbol.name = "bitset";
+ }
+
symbol.value = index.SymbolBitSetValue {
expr = v.elem,
bitset_name = ident,
@@ -1735,7 +1760,7 @@ make_symbol_bitset_from_ast :: proc(ast_context: ^AstContext, v: ast.Bit_Set_Typ
return symbol;
}
-make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type, ident: string) -> index.Symbol {
+make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type, ident: string, inlined := false) -> index.Symbol {
symbol := index.Symbol {
range = common.get_token_range(v, ast_context.file.src),
@@ -1743,6 +1768,11 @@ make_symbol_struct_from_ast :: proc(ast_context: ^AstContext, v: ast.Struct_Type
pkg = get_package_from_node(v.node),
};
+ if inlined {
+ symbol.flags |= {.Anonymous};
+ symbol.name = "struct";
+ }
+
names := make([dynamic]string, context.temp_allocator);
types := make([dynamic]^ast.Expr, context.temp_allocator);
usings := make(map[string]bool, 0, context.temp_allocator);
@@ -2505,6 +2535,17 @@ get_call_commas :: proc(position_context: ^DocumentPositionContext, document: ^c
position_context.call_commas = commas[:];
}
+type_to_string :: proc(ast_context: ^AstContext, expr: ^ast.Expr) -> string {
+
+ if symbol, ok := resolve_type_expression(ast_context, expr); ok {
+ if .Anonymous in symbol.flags {
+ return symbol.name;
+ }
+ }
+
+ return common.node_to_string(expr);
+}
+
/*
Figure out what exactly is at the given position and whether it is in a function, struct, etc.
*/
diff --git a/src/index/collector.odin b/src/index/collector.odin
index 74c47e1..11e949a 100644
--- a/src/index/collector.odin
+++ b/src/index/collector.odin
@@ -371,9 +371,18 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri
symbol.pkg = get_index_unique_string(collection, directory);
symbol.type = token_type;
symbol.doc = common.get_doc(expr.docs, collection.allocator);
- symbol.is_deprecated = expr.deprecated;
- symbol.is_private_file = expr.file_private;
- symbol.is_private_package = expr.package_private;
+
+ if expr.deprecated {
+ symbol.flags |= {.Deprecated};
+ }
+
+ if expr.file_private {
+ symbol.flags |= {.PrivateFile};
+ }
+
+ if expr.package_private {
+ symbol.flags |= {.PrivatePackage};
+ }
when ODIN_OS == "windows" {
symbol.uri = get_index_unique_string(collection, strings.to_lower(uri, context.temp_allocator));
diff --git a/src/index/symbol.odin b/src/index/symbol.odin
index 8e13786..e2ebad5 100644
--- a/src/index/symbol.odin
+++ b/src/index/symbol.odin
@@ -102,6 +102,16 @@ SymbolValue :: union {
SymbolUntypedValue,
}
+SymbolFlag :: enum {
+ Distinct,
+ Deprecated,
+ PrivateFile,
+ PrivatePackage,
+ Anonymous,
+}
+
+SymbolFlags :: bit_set[SymbolFlag]
+
Symbol :: struct {
range: common.Range,
uri: string,
@@ -114,10 +124,7 @@ Symbol :: struct {
value: SymbolValue,
references: []common.Location,
pointers: int,
- is_distinct: bool,
- is_deprecated: bool,
- is_private_file: bool,
- is_private_package: bool,
+ flags: SymbolFlags,
}
SymbolType :: enum {
diff --git a/src/server/completion.odin b/src/server/completion.odin
index b9d17a9..ce0e872 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -408,7 +408,6 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
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;
}
@@ -421,7 +420,7 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
item := CompletionItem {
label = name,
kind = .Field,
- detail = fmt.tprintf("%v.%v: %v", selector.name, name, common.node_to_string(v.types[i])),
+ detail = fmt.tprintf("%v.%v: %v", selector.name, name, type_to_string(ast_context, v.types[i])),
documentation = symbol.doc,
};
@@ -463,7 +462,7 @@ get_selector_completion :: proc(ast_context: ^analysis.AstContext, position_cont
item.insertText = fmt.tprintf("%v($0)", item.label);
item.insertTextFormat = .Snippet;
item.command.command = "editor.action.triggerParameterHints";
- item.deprecated = symbol.is_deprecated;
+ item.deprecated = .Deprecated in symbol.flags;
}
append(&items, item);
@@ -1041,7 +1040,7 @@ get_identifier_completion :: proc(ast_context: ^analysis.AstContext, position_co
if result.symbol.type == .Function {
item.insertText = fmt.tprintf("%v($0)", item.label);
item.insertTextFormat = .Snippet;
- item.deprecated = result.symbol.is_deprecated;
+ item.deprecated = .Deprecated in result.symbol.flags;
item.command.command = "editor.action.triggerParameterHints";
}
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index f4e9a7e..a9c1d0e 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -1009,7 +1009,7 @@ ast_implicit_named_comp_lit_bitset :: proc(t: ^testing.T) {
}
`,
};
-
+
test.expect_completion_details(t, &source, ".", {"A", "B", "C"});
}
@@ -1085,6 +1085,49 @@ ast_implicit_mixed_named_and_unnamed_comp_lit_bitset :: proc(t: ^testing.T) {
test.expect_completion_details(t, &source, ".", {"A", "B", "C"});
}
+@(test)
+ast_inlined_struct :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+ import "my_package"
+
+ My_Struct :: struct {
+ foo: struct {
+ a: int,
+ b: int,
+ },
+ }
+
+ main :: proc() {
+ inst: My_Struct
+ inst.foo.*
+ }
+ `,
+ };
+
+ test.expect_completion_details(t, &source, ".", {"struct.a: int", "struct.b: int"});
+}
+
+@(test)
+ast_inlined_union :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+ import "my_package"
+
+ My_Struct :: struct {
+ variant: union {int, f32},
+ }
+
+ main :: proc() {
+ inst: My_Struct
+ inst.*
+ }
+ `,
+ };
+
+ test.expect_completion_details(t, &source, ".", {"My_Struct.variant: union"});
+}
+
/*
Looks like a bug in for each on w.*